#! /usr/bin/env escript
%% -*- erlang -*-

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

% The current Erlang version
-define(VERSION, "1:27.3.4.6+dfsg").
-define(ABI_VERSION, "17.0").
-define(PCRE_VERSION, "8.45").

% Since all packages required built application to run may be unavailable
% on build stage it's necessary to list all module-package relationships
% explicitly:
-define(MODULES, [{"target_system", "erlang-base"},
{"alarm_handler", "erlang-base"},
{"sasl_report", "erlang-base"},
{"systools_rc", "erlang-base"},
{"erlsrv", "erlang-base"},
{"rb", "erlang-base"},
{"misc_supp", "erlang-base"},
{"format_lib_supp", "erlang-base"},
{"systools_make", "erlang-base"},
{"sasl_report_tty_h", "erlang-base"},
{"release_handler_1", "erlang-base"},
{"systools_relup", "erlang-base"},
{"systools", "erlang-base"},
{"rb_format_supp", "erlang-base"},
{"systools_lib", "erlang-base"},
{"sasl_report_file_h", "erlang-base"},
{"release_handler", "erlang-base"},
{"sasl", "erlang-base"},
{"beam_ssa_share", "erlang-base"},
{"beam_ssa_throw", "erlang-base"},
{"beam_utils", "erlang-base"},
{"cerl_clauses", "erlang-base"},
{"sys_core_bsm", "erlang-base"},
{"sys_core_alias", "erlang-base"},
{"cerl_trees", "erlang-base"},
{"beam_ssa_type", "erlang-base"},
{"beam_bounds", "erlang-base"},
{"compile", "erlang-base"},
{"beam_ssa_bsm", "erlang-base"},
{"beam_digraph", "erlang-base"},
{"beam_opcodes", "erlang-base"},
{"beam_doc", "erlang-base"},
{"v3_core", "erlang-base"},
{"core_lint", "erlang-base"},
{"beam_clean", "erlang-base"},
{"beam_ssa_check", "erlang-base"},
{"beam_disasm", "erlang-base"},
{"sys_core_fold_lists", "erlang-base"},
{"beam_a", "erlang-base"},
{"beam_jump", "erlang-base"},
{"sys_messages", "erlang-base"},
{"beam_ssa_codegen", "erlang-base"},
{"beam_flatten", "erlang-base"},
{"beam_ssa_pre_codegen", "erlang-base"},
{"beam_types", "erlang-base"},
{"beam_call_types", "erlang-base"},
{"beam_ssa_ss", "erlang-base"},
{"beam_trim", "erlang-base"},
{"cerl", "erlang-base"},
{"beam_ssa_lint", "erlang-base"},
{"beam_ssa_pp", "erlang-base"},
{"sys_core_prepare", "erlang-base"},
{"beam_block", "erlang-base"},
{"beam_ssa_recv", "erlang-base"},
{"rec_env", "erlang-base"},
{"sys_coverage", "erlang-base"},
{"beam_asm", "erlang-base"},
{"core_parse", "erlang-base"},
{"core_pp", "erlang-base"},
{"sys_pre_attributes", "erlang-base"},
{"beam_ssa_destructive_update", "erlang-base"},
{"sys_core_inline", "erlang-base"},
{"core_scan", "erlang-base"},
{"sys_core_fold", "erlang-base"},
{"beam_validator", "erlang-base"},
{"beam_dict", "erlang-base"},
{"beam_ssa_bool", "erlang-base"},
{"beam_z", "erlang-base"},
{"cerl_inline", "erlang-base"},
{"beam_ssa_dead", "erlang-base"},
{"beam_ssa_alias", "erlang-base"},
{"erl_bifs", "erlang-base"},
{"beam_ssa", "erlang-base"},
{"beam_ssa_bc_size", "erlang-base"},
{"core_lib", "erlang-base"},
{"beam_listing", "erlang-base"},
{"beam_core_to_ssa", "erlang-base"},
{"beam_ssa_opt", "erlang-base"},
{"erl_prim_loader", "erlang-base"},
{"prim_net", "erlang-base"},
{"zlib", "erlang-base"},
{"prim_zip", "erlang-base"},
{"socket_registry", "erlang-base"},
{"prim_socket", "erlang-base"},
{"atomics", "erlang-base"},
{"prim_eval", "erlang-base"},
{"init", "erlang-base"},
{"prim_buffer", "erlang-base"},
{"persistent_term", "erlang-base"},
{"prim_file", "erlang-base"},
{"erlang", "erlang-base"},
{"erl_tracer", "erlang-base"},
{"prim_inet", "erlang-base"},
{"counters", "erlang-base"},
{"erl_init", "erlang-base"},
{"erts_internal", "erlang-base"},
{"erts_trace_cleaner", "erlang-base"},
{"erts_literal_area_collector", "erlang-base"},
{"erts_code_purger", "erlang-base"},
{"erts_dirty_process_signal_handler", "erlang-base"},
{"math", "erlang-base"},
{"eval_bits", "erlang-base"},
{"gen_fsm", "erlang-base"},
{"supervisor", "erlang-base"},
{"string", "erlang-base"},
{"edlin", "erlang-base"},
{"orddict", "erlang-base"},
{"gen_server", "erlang-base"},
{"timer", "erlang-base"},
{"filelib", "erlang-base"},
{"otp_internal", "erlang-base"},
{"file_sorter", "erlang-base"},
{"escript", "erlang-base"},
{"dict", "erlang-base"},
{"io_lib", "erlang-base"},
{"edlin_context", "erlang-base"},
{"peer", "erlang-base"},
{"edlin_expand", "erlang-base"},
{"edlin_key", "erlang-base"},
{"shell_docs", "erlang-base"},
{"dets_utils", "erlang-base"},
{"io_lib_pretty", "erlang-base"},
{"json", "erlang-base"},
{"log_mf_h", "erlang-base"},
{"base64", "erlang-base"},
{"random", "erlang-base"},
{"unicode_util", "erlang-base"},
{"erl_scan", "erlang-base"},
{"erl_internal", "erlang-base"},
{"erl_tar", "erlang-base"},
{"ets", "erlang-base"},
{"zip", "erlang-base"},
{"erl_features", "erlang-base"},
{"argparse", "erlang-base"},
{"epp", "erlang-base"},
{"proc_lib", "erlang-base"},
{"pool", "erlang-base"},
{"error_logger_file_h", "erlang-base"},
{"erl_abstract_code", "erlang-base"},
{"binary", "erlang-base"},
{"erl_pp", "erlang-base"},
{"error_logger_tty_h", "erlang-base"},
{"calendar", "erlang-base"},
{"io_lib_fread", "erlang-base"},
{"supervisor_bridge", "erlang-base"},
{"queue", "erlang-base"},
{"gb_trees", "erlang-base"},
{"dets", "erlang-base"},
{"qlc_pt", "erlang-base"},
{"erl_anno", "erlang-base"},
{"shell_default", "erlang-base"},
{"gb_sets", "erlang-base"},
{"dets_sup", "erlang-base"},
{"shell", "erlang-base"},
{"erl_eval", "erlang-base"},
{"gen_event", "erlang-base"},
{"ordsets", "erlang-base"},
{"digraph", "erlang-base"},
{"erl_parse", "erlang-base"},
{"io_lib_format", "erlang-base"},
{"sets", "erlang-base"},
{"proplists", "erlang-base"},
{"gen_statem", "erlang-base"},
{"erl_posix_msg", "erlang-base"},
{"filename", "erlang-base"},
{"re", "erlang-base"},
{"io", "erlang-base"},
{"lists", "erlang-base"},
{"sys", "erlang-base"},
{"maps", "erlang-base"},
{"dets_server", "erlang-base"},
{"erl_stdlib_errors", "erlang-base"},
{"erl_lint", "erlang-base"},
{"digraph_utils", "erlang-base"},
{"c", "erlang-base"},
{"ms_transform", "erlang-base"},
{"edlin_type_suggestion", "erlang-base"},
{"unicode", "erlang-base"},
{"gen", "erlang-base"},
{"erl_compile", "erlang-base"},
{"rand", "erlang-base"},
{"erl_error", "erlang-base"},
{"shell_docs_markdown", "erlang-base"},
{"sofs", "erlang-base"},
{"uri_string", "erlang-base"},
{"slave", "erlang-base"},
{"erl_expand_records", "erlang-base"},
{"beam_lib", "erlang-base"},
{"win32reg", "erlang-base"},
{"array", "erlang-base"},
{"dets_v9", "erlang-base"},
{"qlc", "erlang-base"},
{"erl_bits", "erlang-base"},
{"disk_log_server", "erlang-base"},
{"global_group", "erlang-base"},
{"logger_h_common", "erlang-base"},
{"pg2", "erlang-base"},
{"inet_hosts", "erlang-base"},
{"raw_file_io", "erlang-base"},
{"raw_file_io_list", "erlang-base"},
{"net_kernel", "erlang-base"},
{"disk_log", "erlang-base"},
{"code", "erlang-base"},
{"application_controller", "erlang-base"},
{"logger_proxy", "erlang-base"},
{"raw_file_io_deflate", "erlang-base"},
{"erl_epmd", "erlang-base"},
{"group", "erlang-base"},
{"inet_dns", "erlang-base"},
{"gen_tcp_socket", "erlang-base"},
{"inet_tcp", "erlang-base"},
{"prim_tty", "erlang-base"},
{"inet_tcp_dist", "erlang-base"},
{"gen_tcp", "erlang-base"},
{"erl_boot_server", "erlang-base"},
{"erl_signal_handler", "erlang-base"},
{"dist_util", "erlang-base"},
{"logger", "erlang-base"},
{"socket", "erlang-base"},
{"error_handler", "erlang-base"},
{"inet6_udp", "erlang-base"},
{"pg", "erlang-base"},
{"inet_res", "erlang-base"},
{"gen_udp", "erlang-base"},
{"erl_ddll", "erlang-base"},
{"gen_sctp", "erlang-base"},
{"kernel_refc", "erlang-base"},
{"trace", "erlang-base"},
{"seq_trace", "erlang-base"},
{"erpc", "erlang-base"},
{"inet6_tcp_dist", "erlang-base"},
{"inet_parse", "erlang-base"},
{"user_sup", "erlang-base"},
{"logger_olp", "erlang-base"},
{"rpc", "erlang-base"},
{"os", "erlang-base"},
{"local_tcp", "erlang-base"},
{"inet_epmd_socket", "erlang-base"},
{"logger_server", "erlang-base"},
{"logger_filters", "erlang-base"},
{"disk_log_sup", "erlang-base"},
{"application", "erlang-base"},
{"logger_sup", "erlang-base"},
{"kernel", "erlang-base"},
{"local_udp", "erlang-base"},
{"net_adm", "erlang-base"},
{"logger_disk_log_h", "erlang-base"},
{"application_starter", "erlang-base"},
{"standard_error", "erlang-base"},
{"erl_distribution", "erlang-base"},
{"inet_db", "erlang-base"},
{"logger_handler", "erlang-base"},
{"logger_handler_watcher", "erlang-base"},
{"net", "erlang-base"},
{"auth", "erlang-base"},
{"inet_sctp", "erlang-base"},
{"raw_file_io_inflate", "erlang-base"},
{"erl_kernel_errors", "erlang-base"},
{"inet6_sctp", "erlang-base"},
{"heart", "erlang-base"},
{"ram_file", "erlang-base"},
{"erl_reply", "erlang-base"},
{"file", "erlang-base"},
{"inet_epmd_dist", "erlang-base"},
{"logger_simple_h", "erlang-base"},
{"disk_log_1", "erlang-base"},
{"wrap_log_reader", "erlang-base"},
{"application_master", "erlang-base"},
{"erl_compile_server", "erlang-base"},
{"inet_config", "erlang-base"},
{"erl_erts_errors", "erlang-base"},
{"raw_file_io_compressed", "erlang-base"},
{"gen_udp_socket", "erlang-base"},
{"user_drv", "erlang-base"},
{"file_server", "erlang-base"},
{"logger_backend", "erlang-base"},
{"kernel_config", "erlang-base"},
{"group_history", "erlang-base"},
{"logger_config", "erlang-base"},
{"inet_udp", "erlang-base"},
{"logger_std_h", "erlang-base"},
{"erts_debug", "erlang-base"},
{"inet", "erlang-base"},
{"inet_dns_tsig", "erlang-base"},
{"file_io_server", "erlang-base"},
{"dist_ac", "erlang-base"},
{"error_logger", "erlang-base"},
{"logger_formatter", "erlang-base"},
{"global", "erlang-base"},
{"raw_file_io_delayed", "erlang-base"},
{"global_search", "erlang-base"},
{"code_server", "erlang-base"},
{"inet6_tcp", "erlang-base"},
{"inet_gethost_native", "erlang-base"},
{"asn1_db", "erlang-asn1"},
{"asn1ct", "erlang-asn1"},
{"asn1ct_check", "erlang-asn1"},
{"asn1ct_constructed_ber_bin_v2", "erlang-asn1"},
{"asn1ct_constructed_per", "erlang-asn1"},
{"asn1ct_eval_ext", "erlang-asn1"},
{"asn1ct_func", "erlang-asn1"},
{"asn1ct_gen", "erlang-asn1"},
{"asn1ct_gen_ber_bin_v2", "erlang-asn1"},
{"asn1ct_gen_check", "erlang-asn1"},
{"asn1ct_gen_jer", "erlang-asn1"},
{"asn1ct_gen_per", "erlang-asn1"},
{"asn1ct_imm", "erlang-asn1"},
{"asn1ct_name", "erlang-asn1"},
{"asn1ct_parser2", "erlang-asn1"},
{"asn1ct_partial_decode", "erlang-asn1"},
{"asn1ct_pretty_format", "erlang-asn1"},
{"asn1ct_rtt", "erlang-asn1"},
{"asn1ct_table", "erlang-asn1"},
{"asn1ct_tok", "erlang-asn1"},
{"asn1ct_value", "erlang-asn1"},
{"asn1rt_nif", "erlang-asn1"},
{"ct", "erlang-common-test"},
{"ct_config", "erlang-common-test"},
{"ct_config_plain", "erlang-common-test"},
{"ct_config_xml", "erlang-common-test"},
{"ct_conn_log_h", "erlang-common-test"},
{"ct_cover", "erlang-common-test"},
{"ct_default_gl", "erlang-common-test"},
{"ct_event", "erlang-common-test"},
{"ct_framework", "erlang-common-test"},
{"ct_ftp", "erlang-common-test"},
{"ct_gen_conn", "erlang-common-test"},
{"ct_groups", "erlang-common-test"},
{"ct_hooks", "erlang-common-test"},
{"ct_hooks_lock", "erlang-common-test"},
{"ct_logs", "erlang-common-test"},
{"ct_make", "erlang-common-test"},
{"ct_master", "erlang-common-test"},
{"ct_master_event", "erlang-common-test"},
{"ct_master_logs", "erlang-common-test"},
{"ct_master_status", "erlang-common-test"},
{"ct_netconfc", "erlang-common-test"},
{"ct_property_test", "erlang-common-test"},
{"ct_release_test", "erlang-common-test"},
{"ct_repeat", "erlang-common-test"},
{"ct_rpc", "erlang-common-test"},
{"ct_run", "erlang-common-test"},
{"ct_slave", "erlang-common-test"},
{"ct_snmp", "erlang-common-test"},
{"ct_ssh", "erlang-common-test"},
{"ct_suite", "erlang-common-test"},
{"ct_telnet", "erlang-common-test"},
{"ct_telnet_client", "erlang-common-test"},
{"ct_testspec", "erlang-common-test"},
{"ct_util", "erlang-common-test"},
{"cte_track", "erlang-common-test"},
{"cth_conn_log", "erlang-common-test"},
{"cth_log_redirect", "erlang-common-test"},
{"cth_surefire", "erlang-common-test"},
{"erl2html2", "erlang-common-test"},
{"test_server", "erlang-common-test"},
{"test_server_ctrl", "erlang-common-test"},
{"test_server_gl", "erlang-common-test"},
{"test_server_io", "erlang-common-test"},
{"test_server_node", "erlang-common-test"},
{"test_server_sup", "erlang-common-test"},
{"unix_telnet", "erlang-common-test"},
{"ct_proper_ext", "erlang-common-test"},
{"crypto", "erlang-crypto"},
{"crypto_ec_curves", "erlang-crypto"},
{"dbg_debugged", "erlang-debugger"},
{"dbg_icmd", "erlang-debugger"},
{"dbg_idb", "erlang-debugger"},
{"dbg_ieval", "erlang-debugger"},
{"dbg_iload", "erlang-debugger"},
{"dbg_iserver", "erlang-debugger"},
{"dbg_istk", "erlang-debugger"},
{"dbg_wx_break", "erlang-debugger"},
{"dbg_wx_break_win", "erlang-debugger"},
{"dbg_wx_code", "erlang-debugger"},
{"dbg_wx_filedialog_win", "erlang-debugger"},
{"dbg_wx_interpret", "erlang-debugger"},
{"dbg_wx_mon", "erlang-debugger"},
{"dbg_wx_mon_win", "erlang-debugger"},
{"dbg_wx_settings", "erlang-debugger"},
{"dbg_wx_src_view", "erlang-debugger"},
{"dbg_wx_trace", "erlang-debugger"},
{"dbg_wx_trace_win", "erlang-debugger"},
{"dbg_wx_view", "erlang-debugger"},
{"dbg_wx_win", "erlang-debugger"},
{"dbg_wx_winman", "erlang-debugger"},
{"debugger", "erlang-debugger"},
{"i", "erlang-debugger"},
{"int", "erlang-debugger"},
{"cerl_prettypr", "erlang-dialyzer"},
{"dialyzer", "erlang-dialyzer"},
{"dialyzer_analysis_callgraph", "erlang-dialyzer"},
{"dialyzer_behaviours", "erlang-dialyzer"},
{"dialyzer_callgraph", "erlang-dialyzer"},
{"dialyzer_cl", "erlang-dialyzer"},
{"dialyzer_cl_parse", "erlang-dialyzer"},
{"dialyzer_clean_core", "erlang-dialyzer"},
{"dialyzer_codeserver", "erlang-dialyzer"},
{"dialyzer_contracts", "erlang-dialyzer"},
{"dialyzer_coordinator", "erlang-dialyzer"},
{"dialyzer_cplt", "erlang-dialyzer"},
{"dialyzer_dataflow", "erlang-dialyzer"},
{"dialyzer_dep", "erlang-dialyzer"},
{"dialyzer_dot", "erlang-dialyzer"},
{"dialyzer_incremental", "erlang-dialyzer"},
{"dialyzer_iplt", "erlang-dialyzer"},
{"dialyzer_options", "erlang-dialyzer"},
{"dialyzer_plt", "erlang-dialyzer"},
{"dialyzer_succ_typings", "erlang-dialyzer"},
{"dialyzer_timing", "erlang-dialyzer"},
{"dialyzer_typegraph", "erlang-dialyzer"},
{"dialyzer_typesig", "erlang-dialyzer"},
{"dialyzer_utils", "erlang-dialyzer"},
{"dialyzer_worker", "erlang-dialyzer"},
{"erl_bif_types", "erlang-dialyzer"},
{"erl_types", "erlang-dialyzer"},
{"typer", "erlang-dialyzer"},
{"typer_core", "erlang-dialyzer"},
{"diameter", "erlang-diameter"},
{"diameter_app", "erlang-diameter"},
{"diameter_callback", "erlang-diameter"},
{"diameter_capx", "erlang-diameter"},
{"diameter_codec", "erlang-diameter"},
{"diameter_codegen", "erlang-diameter"},
{"diameter_config", "erlang-diameter"},
{"diameter_config_sup", "erlang-diameter"},
{"diameter_dbg", "erlang-diameter"},
{"diameter_dict_parser", "erlang-diameter"},
{"diameter_dict_scanner", "erlang-diameter"},
{"diameter_dict_util", "erlang-diameter"},
{"diameter_dist", "erlang-diameter"},
{"diameter_etcp", "erlang-diameter"},
{"diameter_etcp_sup", "erlang-diameter"},
{"diameter_exprecs", "erlang-diameter"},
{"diameter_gen", "erlang-diameter"},
{"diameter_gen_acct_rfc6733", "erlang-diameter"},
{"diameter_gen_base_accounting", "erlang-diameter"},
{"diameter_gen_base_rfc3588", "erlang-diameter"},
{"diameter_gen_base_rfc6733", "erlang-diameter"},
{"diameter_gen_doic_rfc7683", "erlang-diameter"},
{"diameter_gen_relay", "erlang-diameter"},
{"diameter_info", "erlang-diameter"},
{"diameter_lib", "erlang-diameter"},
{"diameter_make", "erlang-diameter"},
{"diameter_misc_sup", "erlang-diameter"},
{"diameter_peer", "erlang-diameter"},
{"diameter_peer_fsm", "erlang-diameter"},
{"diameter_peer_fsm_sup", "erlang-diameter"},
{"diameter_reg", "erlang-diameter"},
{"diameter_sctp", "erlang-diameter"},
{"diameter_sctp_sup", "erlang-diameter"},
{"diameter_service", "erlang-diameter"},
{"diameter_service_sup", "erlang-diameter"},
{"diameter_session", "erlang-diameter"},
{"diameter_stats", "erlang-diameter"},
{"diameter_sup", "erlang-diameter"},
{"diameter_sync", "erlang-diameter"},
{"diameter_tcp", "erlang-diameter"},
{"diameter_tcp_sup", "erlang-diameter"},
{"diameter_traffic", "erlang-diameter"},
{"diameter_transport", "erlang-diameter"},
{"diameter_transport_sup", "erlang-diameter"},
{"diameter_types", "erlang-diameter"},
{"diameter_watchdog", "erlang-diameter"},
{"diameter_watchdog_sup", "erlang-diameter"},
{"edoc", "erlang-edoc"},
{"edoc_cli", "erlang-edoc"},
{"edoc_data", "erlang-edoc"},
{"edoc_doclet", "erlang-edoc"},
{"edoc_doclet_chunks", "erlang-edoc"},
{"edoc_doclet_markdown", "erlang-edoc"},
{"edoc_extract", "erlang-edoc"},
{"edoc_html_to_markdown", "erlang-edoc"},
{"edoc_layout", "erlang-edoc"},
{"edoc_layout_chunks", "erlang-edoc"},
{"edoc_lib", "erlang-edoc"},
{"edoc_macros", "erlang-edoc"},
{"edoc_parser", "erlang-edoc"},
{"edoc_refs", "erlang-edoc"},
{"edoc_report", "erlang-edoc"},
{"edoc_run", "erlang-edoc"},
{"edoc_scanner", "erlang-edoc"},
{"edoc_specs", "erlang-edoc"},
{"edoc_tags", "erlang-edoc"},
{"edoc_types", "erlang-edoc"},
{"edoc_wiki", "erlang-edoc"},
{"ELDAPv3", "erlang-eldap"},
{"eldap", "erlang-eldap"},
{"et", "erlang-et"},
{"et_collector", "erlang-et"},
{"et_selector", "erlang-et"},
{"et_viewer", "erlang-et"},
{"et_wx_contents_viewer", "erlang-et"},
{"et_wx_viewer", "erlang-et"},
{"eunit", "erlang-eunit"},
{"eunit_autoexport", "erlang-eunit"},
{"eunit_data", "erlang-eunit"},
{"eunit_lib", "erlang-eunit"},
{"eunit_listener", "erlang-eunit"},
{"eunit_proc", "erlang-eunit"},
{"eunit_serial", "erlang-eunit"},
{"eunit_server", "erlang-eunit"},
{"eunit_striptests", "erlang-eunit"},
{"eunit_surefire", "erlang-eunit"},
{"eunit_test", "erlang-eunit"},
{"eunit_tests", "erlang-eunit"},
{"eunit_tty", "erlang-eunit"},
{"ftp", "erlang-ftp"},
{"ftp_app", "erlang-ftp"},
{"ftp_internal", "erlang-ftp"},
{"ftp_progress", "erlang-ftp"},
{"ftp_response", "erlang-ftp"},
{"ftp_sup", "erlang-ftp"},
{"http_chunk", "erlang-inets"},
{"http_request", "erlang-inets"},
{"http_response", "erlang-inets"},
{"http_transport", "erlang-inets"},
{"http_uri", "erlang-inets"},
{"http_util", "erlang-inets"},
{"httpc", "erlang-inets"},
{"httpc_cookie", "erlang-inets"},
{"httpc_handler", "erlang-inets"},
{"httpc_handler_sup", "erlang-inets"},
{"httpc_manager", "erlang-inets"},
{"httpc_profile_sup", "erlang-inets"},
{"httpc_request", "erlang-inets"},
{"httpc_response", "erlang-inets"},
{"httpc_sup", "erlang-inets"},
{"httpd", "erlang-inets"},
{"httpd_acceptor", "erlang-inets"},
{"httpd_acceptor_sup", "erlang-inets"},
{"httpd_cgi", "erlang-inets"},
{"httpd_conf", "erlang-inets"},
{"httpd_connection_sup", "erlang-inets"},
{"httpd_custom", "erlang-inets"},
{"httpd_custom_api", "erlang-inets"},
{"httpd_esi", "erlang-inets"},
{"httpd_example", "erlang-inets"},
{"httpd_file", "erlang-inets"},
{"httpd_instance_sup", "erlang-inets"},
{"httpd_log", "erlang-inets"},
{"httpd_logger", "erlang-inets"},
{"httpd_manager", "erlang-inets"},
{"httpd_misc_sup", "erlang-inets"},
{"httpd_request", "erlang-inets"},
{"httpd_request_handler", "erlang-inets"},
{"httpd_response", "erlang-inets"},
{"httpd_script_env", "erlang-inets"},
{"httpd_socket", "erlang-inets"},
{"httpd_sup", "erlang-inets"},
{"httpd_util", "erlang-inets"},
{"inets", "erlang-inets"},
{"inets_app", "erlang-inets"},
{"inets_lib", "erlang-inets"},
{"inets_service", "erlang-inets"},
{"inets_sup", "erlang-inets"},
{"inets_trace", "erlang-inets"},
{"mod_actions", "erlang-inets"},
{"mod_alias", "erlang-inets"},
{"mod_auth", "erlang-inets"},
{"mod_auth_dets", "erlang-inets"},
{"mod_auth_mnesia", "erlang-inets"},
{"mod_auth_plain", "erlang-inets"},
{"mod_auth_server", "erlang-inets"},
{"mod_cgi", "erlang-inets"},
{"mod_dir", "erlang-inets"},
{"mod_disk_log", "erlang-inets"},
{"mod_esi", "erlang-inets"},
{"mod_get", "erlang-inets"},
{"mod_head", "erlang-inets"},
{"mod_log", "erlang-inets"},
{"mod_range", "erlang-inets"},
{"mod_responsecontrol", "erlang-inets"},
{"mod_security", "erlang-inets"},
{"mod_security_server", "erlang-inets"},
{"mod_trace", "erlang-inets"},
{"megaco", "erlang-megaco"},
{"megaco_ber_encoder", "erlang-megaco"},
{"megaco_ber_media_gateway_control_v1", "erlang-megaco"},
{"megaco_ber_media_gateway_control_v2", "erlang-megaco"},
{"megaco_ber_media_gateway_control_v3", "erlang-megaco"},
{"megaco_binary_encoder", "erlang-megaco"},
{"megaco_binary_encoder_lib", "erlang-megaco"},
{"megaco_binary_name_resolver_v1", "erlang-megaco"},
{"megaco_binary_name_resolver_v2", "erlang-megaco"},
{"megaco_binary_name_resolver_v3", "erlang-megaco"},
{"megaco_binary_term_id", "erlang-megaco"},
{"megaco_binary_term_id_gen", "erlang-megaco"},
{"megaco_binary_transformer_v1", "erlang-megaco"},
{"megaco_binary_transformer_v2", "erlang-megaco"},
{"megaco_binary_transformer_v3", "erlang-megaco"},
{"megaco_compact_text_encoder", "erlang-megaco"},
{"megaco_compact_text_encoder_v1", "erlang-megaco"},
{"megaco_compact_text_encoder_v2", "erlang-megaco"},
{"megaco_compact_text_encoder_v3", "erlang-megaco"},
{"megaco_config", "erlang-megaco"},
{"megaco_config_misc", "erlang-megaco"},
{"megaco_digit_map", "erlang-megaco"},
{"megaco_edist_compress", "erlang-megaco"},
{"megaco_encoder", "erlang-megaco"},
{"megaco_erl_dist_encoder", "erlang-megaco"},
{"megaco_erl_dist_encoder_mc", "erlang-megaco"},
{"megaco_filter", "erlang-megaco"},
{"megaco_flex_scanner", "erlang-megaco"},
{"megaco_flex_scanner_handler", "erlang-megaco"},
{"megaco_messenger", "erlang-megaco"},
{"megaco_messenger_misc", "erlang-megaco"},
{"megaco_misc_sup", "erlang-megaco"},
{"megaco_monitor", "erlang-megaco"},
{"megaco_per_encoder", "erlang-megaco"},
{"megaco_per_media_gateway_control_v1", "erlang-megaco"},
{"megaco_per_media_gateway_control_v2", "erlang-megaco"},
{"megaco_per_media_gateway_control_v3", "erlang-megaco"},
{"megaco_pretty_text_encoder", "erlang-megaco"},
{"megaco_pretty_text_encoder_v1", "erlang-megaco"},
{"megaco_pretty_text_encoder_v2", "erlang-megaco"},
{"megaco_pretty_text_encoder_v3", "erlang-megaco"},
{"megaco_sdp", "erlang-megaco"},
{"megaco_stats", "erlang-megaco"},
{"megaco_sup", "erlang-megaco"},
{"megaco_tcp", "erlang-megaco"},
{"megaco_tcp_accept", "erlang-megaco"},
{"megaco_tcp_accept_sup", "erlang-megaco"},
{"megaco_tcp_connection", "erlang-megaco"},
{"megaco_tcp_connection_sup", "erlang-megaco"},
{"megaco_tcp_sup", "erlang-megaco"},
{"megaco_text_mini_decoder", "erlang-megaco"},
{"megaco_text_mini_parser", "erlang-megaco"},
{"megaco_text_parser_v1", "erlang-megaco"},
{"megaco_text_parser_v2", "erlang-megaco"},
{"megaco_text_parser_v3", "erlang-megaco"},
{"megaco_text_scanner", "erlang-megaco"},
{"megaco_timer", "erlang-megaco"},
{"megaco_trans_sender", "erlang-megaco"},
{"megaco_trans_sup", "erlang-megaco"},
{"megaco_transport", "erlang-megaco"},
{"megaco_udp", "erlang-megaco"},
{"megaco_udp_server", "erlang-megaco"},
{"megaco_udp_sup", "erlang-megaco"},
{"megaco_user", "erlang-megaco"},
{"megaco_user_default", "erlang-megaco"},
{"mnesia", "erlang-mnesia"},
{"mnesia_app", "erlang-mnesia"},
{"mnesia_backend_type", "erlang-mnesia"},
{"mnesia_backup", "erlang-mnesia"},
{"mnesia_bup", "erlang-mnesia"},
{"mnesia_checkpoint", "erlang-mnesia"},
{"mnesia_checkpoint_sup", "erlang-mnesia"},
{"mnesia_controller", "erlang-mnesia"},
{"mnesia_dumper", "erlang-mnesia"},
{"mnesia_event", "erlang-mnesia"},
{"mnesia_ext_sup", "erlang-mnesia"},
{"mnesia_frag", "erlang-mnesia"},
{"mnesia_frag_hash", "erlang-mnesia"},
{"mnesia_index", "erlang-mnesia"},
{"mnesia_kernel_sup", "erlang-mnesia"},
{"mnesia_late_loader", "erlang-mnesia"},
{"mnesia_lib", "erlang-mnesia"},
{"mnesia_loader", "erlang-mnesia"},
{"mnesia_locker", "erlang-mnesia"},
{"mnesia_log", "erlang-mnesia"},
{"mnesia_monitor", "erlang-mnesia"},
{"mnesia_recover", "erlang-mnesia"},
{"mnesia_registry", "erlang-mnesia"},
{"mnesia_rpc", "erlang-mnesia"},
{"mnesia_schema", "erlang-mnesia"},
{"mnesia_snmp_hook", "erlang-mnesia"},
{"mnesia_sp", "erlang-mnesia"},
{"mnesia_subscr", "erlang-mnesia"},
{"mnesia_sup", "erlang-mnesia"},
{"mnesia_text", "erlang-mnesia"},
{"mnesia_tm", "erlang-mnesia"},
{"cdv_atom_cb", "erlang-observer"},
{"cdv_bin_cb", "erlang-observer"},
{"cdv_detail_wx", "erlang-observer"},
{"cdv_dist_cb", "erlang-observer"},
{"cdv_ets_cb", "erlang-observer"},
{"cdv_fun_cb", "erlang-observer"},
{"cdv_gen_cb", "erlang-observer"},
{"cdv_html_wx", "erlang-observer"},
{"cdv_info_wx", "erlang-observer"},
{"cdv_int_tab_cb", "erlang-observer"},
{"cdv_mem_cb", "erlang-observer"},
{"cdv_mod_cb", "erlang-observer"},
{"cdv_multi_wx", "erlang-observer"},
{"cdv_persistent_cb", "erlang-observer"},
{"cdv_port_cb", "erlang-observer"},
{"cdv_proc_cb", "erlang-observer"},
{"cdv_sched_cb", "erlang-observer"},
{"cdv_table_wx", "erlang-observer"},
{"cdv_term_cb", "erlang-observer"},
{"cdv_timer_cb", "erlang-observer"},
{"cdv_virtual_list_wx", "erlang-observer"},
{"cdv_wx", "erlang-observer"},
{"crashdump_viewer", "erlang-observer"},
{"etop", "erlang-observer"},
{"etop_tr", "erlang-observer"},
{"etop_txt", "erlang-observer"},
{"observer", "erlang-observer"},
{"observer_alloc_wx", "erlang-observer"},
{"observer_app_wx", "erlang-observer"},
{"observer_html_lib", "erlang-observer"},
{"observer_lib", "erlang-observer"},
{"observer_perf_wx", "erlang-observer"},
{"observer_port_wx", "erlang-observer"},
{"observer_pro_wx", "erlang-observer"},
{"observer_procinfo", "erlang-observer"},
{"observer_sock_wx", "erlang-observer"},
{"observer_sys_wx", "erlang-observer"},
{"observer_trace_wx", "erlang-observer"},
{"observer_traceoptions_wx", "erlang-observer"},
{"observer_tv_table", "erlang-observer"},
{"observer_tv_wx", "erlang-observer"},
{"observer_wx", "erlang-observer"},
{"ttb", "erlang-observer"},
{"ttb_et", "erlang-observer"},
{"odbc", "erlang-odbc"},
{"odbc_app", "erlang-odbc"},
{"odbc_sup", "erlang-odbc"},
{"cpu_sup", "erlang-os-mon"},
{"disksup", "erlang-os-mon"},
{"memsup", "erlang-os-mon"},
{"nteventlog", "erlang-os-mon"},
{"os_mon", "erlang-os-mon"},
{"os_mon_mib", "erlang-os-mon"},
{"os_mon_sysinfo", "erlang-os-mon"},
{"os_sup", "erlang-os-mon"},
{"leex", "erlang-parsetools"},
{"yecc", "erlang-parsetools"},
{"yeccparser", "erlang-parsetools"},
{"yeccscan", "erlang-parsetools"},
{"OTP-PUB-KEY", "erlang-public-key"},
{"PKCS-FRAME", "erlang-public-key"},
{"pubkey_cert", "erlang-public-key"},
{"pubkey_cert_records", "erlang-public-key"},
{"pubkey_crl", "erlang-public-key"},
{"pubkey_ocsp", "erlang-public-key"},
{"pubkey_os_cacerts", "erlang-public-key"},
{"pubkey_pbe", "erlang-public-key"},
{"pubkey_pem", "erlang-public-key"},
{"pubkey_policy_tree", "erlang-public-key"},
{"pubkey_ssh", "erlang-public-key"},
{"public_key", "erlang-public-key"},
{"reltool", "erlang-reltool"},
{"reltool_app_win", "erlang-reltool"},
{"reltool_fgraph", "erlang-reltool"},
{"reltool_fgraph_win", "erlang-reltool"},
{"reltool_mod_win", "erlang-reltool"},
{"reltool_server", "erlang-reltool"},
{"reltool_sys_win", "erlang-reltool"},
{"reltool_target", "erlang-reltool"},
{"reltool_utils", "erlang-reltool"},
{"appmon_info", "erlang-runtime-tools"},
{"dbg", "erlang-runtime-tools"},
{"dyntrace", "erlang-runtime-tools"},
{"erts_alloc_config", "erlang-runtime-tools"},
{"instrument", "erlang-runtime-tools"},
{"msacc", "erlang-runtime-tools"},
{"observer_backend", "erlang-runtime-tools"},
{"runtime_tools", "erlang-runtime-tools"},
{"runtime_tools_sup", "erlang-runtime-tools"},
{"scheduler", "erlang-runtime-tools"},
{"system_information", "erlang-runtime-tools"},
{"ttb_autostart", "erlang-runtime-tools"},
{"snmp", "erlang-snmp"},
{"snmp_app", "erlang-snmp"},
{"snmp_app_sup", "erlang-snmp"},
{"snmp_community_mib", "erlang-snmp"},
{"snmp_conf", "erlang-snmp"},
{"snmp_config", "erlang-snmp"},
{"snmp_framework_mib", "erlang-snmp"},
{"snmp_generic", "erlang-snmp"},
{"snmp_generic_mnesia", "erlang-snmp"},
{"snmp_index", "erlang-snmp"},
{"snmp_log", "erlang-snmp"},
{"snmp_mini_mib", "erlang-snmp"},
{"snmp_misc", "erlang-snmp"},
{"snmp_note_store", "erlang-snmp"},
{"snmp_notification_mib", "erlang-snmp"},
{"snmp_pdus", "erlang-snmp"},
{"snmp_shadow_table", "erlang-snmp"},
{"snmp_standard_mib", "erlang-snmp"},
{"snmp_target_mib", "erlang-snmp"},
{"snmp_user_based_sm_mib", "erlang-snmp"},
{"snmp_usm", "erlang-snmp"},
{"snmp_verbosity", "erlang-snmp"},
{"snmp_view_based_acm_mib", "erlang-snmp"},
{"snmpa", "erlang-snmp"},
{"snmpa_acm", "erlang-snmp"},
{"snmpa_agent", "erlang-snmp"},
{"snmpa_agent_sup", "erlang-snmp"},
{"snmpa_app", "erlang-snmp"},
{"snmpa_authentication_service", "erlang-snmp"},
{"snmpa_conf", "erlang-snmp"},
{"snmpa_discovery_handler", "erlang-snmp"},
{"snmpa_discovery_handler_default", "erlang-snmp"},
{"snmpa_error", "erlang-snmp"},
{"snmpa_error_io", "erlang-snmp"},
{"snmpa_error_logger", "erlang-snmp"},
{"snmpa_error_report", "erlang-snmp"},
{"snmpa_get", "erlang-snmp"},
{"snmpa_get_lib", "erlang-snmp"},
{"snmpa_get_mechanism", "erlang-snmp"},
{"snmpa_local_db", "erlang-snmp"},
{"snmpa_mib", "erlang-snmp"},
{"snmpa_mib_data", "erlang-snmp"},
{"snmpa_mib_data_tttn", "erlang-snmp"},
{"snmpa_mib_lib", "erlang-snmp"},
{"snmpa_mib_storage", "erlang-snmp"},
{"snmpa_mib_storage_dets", "erlang-snmp"},
{"snmpa_mib_storage_ets", "erlang-snmp"},
{"snmpa_mib_storage_mnesia", "erlang-snmp"},
{"snmpa_misc_sup", "erlang-snmp"},
{"snmpa_mpd", "erlang-snmp"},
{"snmpa_net_if", "erlang-snmp"},
{"snmpa_net_if_filter", "erlang-snmp"},
{"snmpa_network_interface", "erlang-snmp"},
{"snmpa_network_interface_filter", "erlang-snmp"},
{"snmpa_notification_delivery_info_receiver", "erlang-snmp"},
{"snmpa_notification_filter", "erlang-snmp"},
{"snmpa_set", "erlang-snmp"},
{"snmpa_set_lib", "erlang-snmp"},
{"snmpa_set_mechanism", "erlang-snmp"},
{"snmpa_supervisor", "erlang-snmp"},
{"snmpa_svbl", "erlang-snmp"},
{"snmpa_symbolic_store", "erlang-snmp"},
{"snmpa_target_cache", "erlang-snmp"},
{"snmpa_trap", "erlang-snmp"},
{"snmpa_usm", "erlang-snmp"},
{"snmpa_vacm", "erlang-snmp"},
{"snmpc", "erlang-snmp"},
{"snmpc_lib", "erlang-snmp"},
{"snmpc_mib_gram", "erlang-snmp"},
{"snmpc_mib_to_hrl", "erlang-snmp"},
{"snmpc_misc", "erlang-snmp"},
{"snmpc_tok", "erlang-snmp"},
{"snmpm", "erlang-snmp"},
{"snmpm_conf", "erlang-snmp"},
{"snmpm_config", "erlang-snmp"},
{"snmpm_misc_sup", "erlang-snmp"},
{"snmpm_mpd", "erlang-snmp"},
{"snmpm_net_if", "erlang-snmp"},
{"snmpm_net_if_filter", "erlang-snmp"},
{"snmpm_net_if_mt", "erlang-snmp"},
{"snmpm_network_interface", "erlang-snmp"},
{"snmpm_network_interface_filter", "erlang-snmp"},
{"snmpm_server", "erlang-snmp"},
{"snmpm_server_sup", "erlang-snmp"},
{"snmpm_supervisor", "erlang-snmp"},
{"snmpm_user", "erlang-snmp"},
{"snmpm_user_default", "erlang-snmp"},
{"snmpm_user_old", "erlang-snmp"},
{"snmpm_usm", "erlang-snmp"},
{"ssh", "erlang-ssh"},
{"ssh_acceptor", "erlang-ssh"},
{"ssh_acceptor_sup", "erlang-ssh"},
{"ssh_agent", "erlang-ssh"},
{"ssh_app", "erlang-ssh"},
{"ssh_auth", "erlang-ssh"},
{"ssh_bits", "erlang-ssh"},
{"ssh_channel", "erlang-ssh"},
{"ssh_channel_sup", "erlang-ssh"},
{"ssh_cli", "erlang-ssh"},
{"ssh_client_channel", "erlang-ssh"},
{"ssh_client_key_api", "erlang-ssh"},
{"ssh_connection", "erlang-ssh"},
{"ssh_connection_handler", "erlang-ssh"},
{"ssh_connection_sup", "erlang-ssh"},
{"ssh_daemon_channel", "erlang-ssh"},
{"ssh_dbg", "erlang-ssh"},
{"ssh_file", "erlang-ssh"},
{"ssh_fsm_kexinit", "erlang-ssh"},
{"ssh_fsm_userauth_client", "erlang-ssh"},
{"ssh_fsm_userauth_server", "erlang-ssh"},
{"ssh_info", "erlang-ssh"},
{"ssh_io", "erlang-ssh"},
{"ssh_lib", "erlang-ssh"},
{"ssh_message", "erlang-ssh"},
{"ssh_no_io", "erlang-ssh"},
{"ssh_options", "erlang-ssh"},
{"ssh_server_channel", "erlang-ssh"},
{"ssh_server_key_api", "erlang-ssh"},
{"ssh_sftp", "erlang-ssh"},
{"ssh_sftpd", "erlang-ssh"},
{"ssh_sftpd_file", "erlang-ssh"},
{"ssh_sftpd_file_api", "erlang-ssh"},
{"ssh_shell", "erlang-ssh"},
{"ssh_system_sup", "erlang-ssh"},
{"ssh_tcpip_forward_acceptor", "erlang-ssh"},
{"ssh_tcpip_forward_acceptor_sup", "erlang-ssh"},
{"ssh_tcpip_forward_client", "erlang-ssh"},
{"ssh_tcpip_forward_srv", "erlang-ssh"},
{"ssh_transport", "erlang-ssh"},
{"ssh_xfer", "erlang-ssh"},
{"dtls_client_connection", "erlang-ssl"},
{"dtls_connection_sup", "erlang-ssl"},
{"dtls_gen_connection", "erlang-ssl"},
{"dtls_handshake", "erlang-ssl"},
{"dtls_listener_sup", "erlang-ssl"},
{"dtls_packet_demux", "erlang-ssl"},
{"dtls_record", "erlang-ssl"},
{"dtls_server_connection", "erlang-ssl"},
{"dtls_server_session_cache_sup", "erlang-ssl"},
{"dtls_server_sup", "erlang-ssl"},
{"dtls_socket", "erlang-ssl"},
{"dtls_sup", "erlang-ssl"},
{"dtls_v1", "erlang-ssl"},
{"inet6_tls_dist", "erlang-ssl"},
{"inet_tls_dist", "erlang-ssl"},
{"ssl", "erlang-ssl"},
{"ssl_admin_sup", "erlang-ssl"},
{"ssl_alert", "erlang-ssl"},
{"ssl_app", "erlang-ssl"},
{"ssl_certificate", "erlang-ssl"},
{"ssl_cipher", "erlang-ssl"},
{"ssl_cipher_format", "erlang-ssl"},
{"ssl_client_session_cache_db", "erlang-ssl"},
{"ssl_config", "erlang-ssl"},
{"ssl_connection_sup", "erlang-ssl"},
{"ssl_crl", "erlang-ssl"},
{"ssl_crl_cache", "erlang-ssl"},
{"ssl_crl_cache_api", "erlang-ssl"},
{"ssl_crl_hash_dir", "erlang-ssl"},
{"ssl_dh_groups", "erlang-ssl"},
{"ssl_dist_admin_sup", "erlang-ssl"},
{"ssl_dist_connection_sup", "erlang-ssl"},
{"ssl_dist_sup", "erlang-ssl"},
{"ssl_gen_statem", "erlang-ssl"},
{"ssl_handshake", "erlang-ssl"},
{"ssl_listen_tracker_sup", "erlang-ssl"},
{"ssl_logger", "erlang-ssl"},
{"ssl_manager", "erlang-ssl"},
{"ssl_pem_cache", "erlang-ssl"},
{"ssl_pkix_db", "erlang-ssl"},
{"ssl_record", "erlang-ssl"},
{"ssl_server_session_cache", "erlang-ssl"},
{"ssl_server_session_cache_db", "erlang-ssl"},
{"ssl_server_session_cache_sup", "erlang-ssl"},
{"ssl_session", "erlang-ssl"},
{"ssl_session_cache_api", "erlang-ssl"},
{"ssl_srp_primes", "erlang-ssl"},
{"ssl_sup", "erlang-ssl"},
{"ssl_trace", "erlang-ssl"},
{"ssl_upgrade_server_session_cache_sup", "erlang-ssl"},
{"tls_bloom_filter", "erlang-ssl"},
{"tls_client_connection", "erlang-ssl"},
{"tls_client_connection_1_3", "erlang-ssl"},
{"tls_client_ticket_store", "erlang-ssl"},
{"tls_connection_sup", "erlang-ssl"},
{"tls_dist_server_sup", "erlang-ssl"},
{"tls_dist_sup", "erlang-ssl"},
{"tls_dtls_client_connection", "erlang-ssl"},
{"tls_dtls_gen_connection", "erlang-ssl"},
{"tls_dtls_server_connection", "erlang-ssl"},
{"tls_dyn_connection_sup", "erlang-ssl"},
{"tls_gen_connection", "erlang-ssl"},
{"tls_gen_connection_1_3", "erlang-ssl"},
{"tls_handshake", "erlang-ssl"},
{"tls_handshake_1_3", "erlang-ssl"},
{"tls_record", "erlang-ssl"},
{"tls_record_1_3", "erlang-ssl"},
{"tls_sender", "erlang-ssl"},
{"tls_server_connection", "erlang-ssl"},
{"tls_server_connection_1_3", "erlang-ssl"},
{"tls_server_session_ticket", "erlang-ssl"},
{"tls_server_session_ticket_sup", "erlang-ssl"},
{"tls_server_sup", "erlang-ssl"},
{"tls_socket", "erlang-ssl"},
{"tls_sup", "erlang-ssl"},
{"tls_v1", "erlang-ssl"},
{"epp_dodger", "erlang-syntax-tools"},
{"erl_comment_scan", "erlang-syntax-tools"},
{"erl_prettypr", "erlang-syntax-tools"},
{"erl_recomment", "erlang-syntax-tools"},
{"erl_syntax", "erlang-syntax-tools"},
{"erl_syntax_lib", "erlang-syntax-tools"},
{"merl", "erlang-syntax-tools"},
{"merl_transform", "erlang-syntax-tools"},
{"prettypr", "erlang-syntax-tools"},
{"tftp", "erlang-tftp"},
{"tftp_app", "erlang-tftp"},
{"tftp_binary", "erlang-tftp"},
{"tftp_engine", "erlang-tftp"},
{"tftp_file", "erlang-tftp"},
{"tftp_lib", "erlang-tftp"},
{"tftp_logger", "erlang-tftp"},
{"tftp_sup", "erlang-tftp"},
{"cover", "erlang-tools"},
{"cprof", "erlang-tools"},
{"eprof", "erlang-tools"},
{"fprof", "erlang-tools"},
{"lcnt", "erlang-tools"},
{"make", "erlang-tools"},
{"tags", "erlang-tools"},
{"tprof", "erlang-tools"},
{"xref", "erlang-tools"},
{"xref_base", "erlang-tools"},
{"xref_compiler", "erlang-tools"},
{"xref_parser", "erlang-tools"},
{"xref_reader", "erlang-tools"},
{"xref_scanner", "erlang-tools"},
{"xref_utils", "erlang-tools"},
{"gl", "erlang-wx"},
{"glu", "erlang-wx"},
{"wx", "erlang-wx"},
{"wxAcceleratorEntry", "erlang-wx"},
{"wxAcceleratorTable", "erlang-wx"},
{"wxActivateEvent", "erlang-wx"},
{"wxArtProvider", "erlang-wx"},
{"wxAuiDockArt", "erlang-wx"},
{"wxAuiManager", "erlang-wx"},
{"wxAuiManagerEvent", "erlang-wx"},
{"wxAuiNotebook", "erlang-wx"},
{"wxAuiNotebookEvent", "erlang-wx"},
{"wxAuiPaneInfo", "erlang-wx"},
{"wxAuiSimpleTabArt", "erlang-wx"},
{"wxAuiTabArt", "erlang-wx"},
{"wxBitmap", "erlang-wx"},
{"wxBitmapButton", "erlang-wx"},
{"wxBitmapDataObject", "erlang-wx"},
{"wxBookCtrlBase", "erlang-wx"},
{"wxBookCtrlEvent", "erlang-wx"},
{"wxBoxSizer", "erlang-wx"},
{"wxBrush", "erlang-wx"},
{"wxBufferedDC", "erlang-wx"},
{"wxBufferedPaintDC", "erlang-wx"},
{"wxButton", "erlang-wx"},
{"wxCalendarCtrl", "erlang-wx"},
{"wxCalendarDateAttr", "erlang-wx"},
{"wxCalendarEvent", "erlang-wx"},
{"wxCaret", "erlang-wx"},
{"wxCheckBox", "erlang-wx"},
{"wxCheckListBox", "erlang-wx"},
{"wxChildFocusEvent", "erlang-wx"},
{"wxChoice", "erlang-wx"},
{"wxChoicebook", "erlang-wx"},
{"wxClientDC", "erlang-wx"},
{"wxClipboard", "erlang-wx"},
{"wxClipboardTextEvent", "erlang-wx"},
{"wxCloseEvent", "erlang-wx"},
{"wxColourData", "erlang-wx"},
{"wxColourDialog", "erlang-wx"},
{"wxColourPickerCtrl", "erlang-wx"},
{"wxColourPickerEvent", "erlang-wx"},
{"wxComboBox", "erlang-wx"},
{"wxCommandEvent", "erlang-wx"},
{"wxContextMenuEvent", "erlang-wx"},
{"wxControl", "erlang-wx"},
{"wxControlWithItems", "erlang-wx"},
{"wxCursor", "erlang-wx"},
{"wxDC", "erlang-wx"},
{"wxDCOverlay", "erlang-wx"},
{"wxDataObject", "erlang-wx"},
{"wxDateEvent", "erlang-wx"},
{"wxDatePickerCtrl", "erlang-wx"},
{"wxDialog", "erlang-wx"},
{"wxDirDialog", "erlang-wx"},
{"wxDirPickerCtrl", "erlang-wx"},
{"wxDisplay", "erlang-wx"},
{"wxDisplayChangedEvent", "erlang-wx"},
{"wxDropFilesEvent", "erlang-wx"},
{"wxEraseEvent", "erlang-wx"},
{"wxEvent", "erlang-wx"},
{"wxEvtHandler", "erlang-wx"},
{"wxFileDataObject", "erlang-wx"},
{"wxFileDialog", "erlang-wx"},
{"wxFileDirPickerEvent", "erlang-wx"},
{"wxFilePickerCtrl", "erlang-wx"},
{"wxFindReplaceData", "erlang-wx"},
{"wxFindReplaceDialog", "erlang-wx"},
{"wxFlexGridSizer", "erlang-wx"},
{"wxFocusEvent", "erlang-wx"},
{"wxFont", "erlang-wx"},
{"wxFontData", "erlang-wx"},
{"wxFontDialog", "erlang-wx"},
{"wxFontPickerCtrl", "erlang-wx"},
{"wxFontPickerEvent", "erlang-wx"},
{"wxFrame", "erlang-wx"},
{"wxGBSizerItem", "erlang-wx"},
{"wxGCDC", "erlang-wx"},
{"wxGLCanvas", "erlang-wx"},
{"wxGLContext", "erlang-wx"},
{"wxGauge", "erlang-wx"},
{"wxGenericDirCtrl", "erlang-wx"},
{"wxGraphicsBrush", "erlang-wx"},
{"wxGraphicsContext", "erlang-wx"},
{"wxGraphicsFont", "erlang-wx"},
{"wxGraphicsGradientStops", "erlang-wx"},
{"wxGraphicsMatrix", "erlang-wx"},
{"wxGraphicsObject", "erlang-wx"},
{"wxGraphicsPath", "erlang-wx"},
{"wxGraphicsPen", "erlang-wx"},
{"wxGraphicsRenderer", "erlang-wx"},
{"wxGrid", "erlang-wx"},
{"wxGridBagSizer", "erlang-wx"},
{"wxGridCellAttr", "erlang-wx"},
{"wxGridCellBoolEditor", "erlang-wx"},
{"wxGridCellBoolRenderer", "erlang-wx"},
{"wxGridCellChoiceEditor", "erlang-wx"},
{"wxGridCellEditor", "erlang-wx"},
{"wxGridCellFloatEditor", "erlang-wx"},
{"wxGridCellFloatRenderer", "erlang-wx"},
{"wxGridCellNumberEditor", "erlang-wx"},
{"wxGridCellNumberRenderer", "erlang-wx"},
{"wxGridCellRenderer", "erlang-wx"},
{"wxGridCellStringRenderer", "erlang-wx"},
{"wxGridCellTextEditor", "erlang-wx"},
{"wxGridEvent", "erlang-wx"},
{"wxGridSizer", "erlang-wx"},
{"wxHelpEvent", "erlang-wx"},
{"wxHtmlEasyPrinting", "erlang-wx"},
{"wxHtmlLinkEvent", "erlang-wx"},
{"wxHtmlWindow", "erlang-wx"},
{"wxIcon", "erlang-wx"},
{"wxIconBundle", "erlang-wx"},
{"wxIconizeEvent", "erlang-wx"},
{"wxIdleEvent", "erlang-wx"},
{"wxImage", "erlang-wx"},
{"wxImageList", "erlang-wx"},
{"wxInitDialogEvent", "erlang-wx"},
{"wxJoystickEvent", "erlang-wx"},
{"wxKeyEvent", "erlang-wx"},
{"wxLayoutAlgorithm", "erlang-wx"},
{"wxListBox", "erlang-wx"},
{"wxListCtrl", "erlang-wx"},
{"wxListEvent", "erlang-wx"},
{"wxListItem", "erlang-wx"},
{"wxListItemAttr", "erlang-wx"},
{"wxListView", "erlang-wx"},
{"wxListbook", "erlang-wx"},
{"wxLocale", "erlang-wx"},
{"wxLogNull", "erlang-wx"},
{"wxMDIChildFrame", "erlang-wx"},
{"wxMDIClientWindow", "erlang-wx"},
{"wxMDIParentFrame", "erlang-wx"},
{"wxMask", "erlang-wx"},
{"wxMaximizeEvent", "erlang-wx"},
{"wxMemoryDC", "erlang-wx"},
{"wxMenu", "erlang-wx"},
{"wxMenuBar", "erlang-wx"},
{"wxMenuEvent", "erlang-wx"},
{"wxMenuItem", "erlang-wx"},
{"wxMessageDialog", "erlang-wx"},
{"wxMiniFrame", "erlang-wx"},
{"wxMirrorDC", "erlang-wx"},
{"wxMouseCaptureChangedEvent", "erlang-wx"},
{"wxMouseCaptureLostEvent", "erlang-wx"},
{"wxMouseEvent", "erlang-wx"},
{"wxMoveEvent", "erlang-wx"},
{"wxMultiChoiceDialog", "erlang-wx"},
{"wxNavigationKeyEvent", "erlang-wx"},
{"wxNotebook", "erlang-wx"},
{"wxNotificationMessage", "erlang-wx"},
{"wxNotifyEvent", "erlang-wx"},
{"wxOverlay", "erlang-wx"},
{"wxPageSetupDialog", "erlang-wx"},
{"wxPageSetupDialogData", "erlang-wx"},
{"wxPaintDC", "erlang-wx"},
{"wxPaintEvent", "erlang-wx"},
{"wxPalette", "erlang-wx"},
{"wxPaletteChangedEvent", "erlang-wx"},
{"wxPanel", "erlang-wx"},
{"wxPasswordEntryDialog", "erlang-wx"},
{"wxPen", "erlang-wx"},
{"wxPickerBase", "erlang-wx"},
{"wxPopupTransientWindow", "erlang-wx"},
{"wxPopupWindow", "erlang-wx"},
{"wxPostScriptDC", "erlang-wx"},
{"wxPreviewCanvas", "erlang-wx"},
{"wxPreviewControlBar", "erlang-wx"},
{"wxPreviewFrame", "erlang-wx"},
{"wxPrintData", "erlang-wx"},
{"wxPrintDialog", "erlang-wx"},
{"wxPrintDialogData", "erlang-wx"},
{"wxPrintPreview", "erlang-wx"},
{"wxPrinter", "erlang-wx"},
{"wxPrintout", "erlang-wx"},
{"wxProgressDialog", "erlang-wx"},
{"wxQueryNewPaletteEvent", "erlang-wx"},
{"wxRadioBox", "erlang-wx"},
{"wxRadioButton", "erlang-wx"},
{"wxRegion", "erlang-wx"},
{"wxSashEvent", "erlang-wx"},
{"wxSashLayoutWindow", "erlang-wx"},
{"wxSashWindow", "erlang-wx"},
{"wxScreenDC", "erlang-wx"},
{"wxScrollBar", "erlang-wx"},
{"wxScrollEvent", "erlang-wx"},
{"wxScrollWinEvent", "erlang-wx"},
{"wxScrolledWindow", "erlang-wx"},
{"wxSetCursorEvent", "erlang-wx"},
{"wxShowEvent", "erlang-wx"},
{"wxSingleChoiceDialog", "erlang-wx"},
{"wxSizeEvent", "erlang-wx"},
{"wxSizer", "erlang-wx"},
{"wxSizerFlags", "erlang-wx"},
{"wxSizerItem", "erlang-wx"},
{"wxSlider", "erlang-wx"},
{"wxSpinButton", "erlang-wx"},
{"wxSpinCtrl", "erlang-wx"},
{"wxSpinEvent", "erlang-wx"},
{"wxSplashScreen", "erlang-wx"},
{"wxSplitterEvent", "erlang-wx"},
{"wxSplitterWindow", "erlang-wx"},
{"wxStaticBitmap", "erlang-wx"},
{"wxStaticBox", "erlang-wx"},
{"wxStaticBoxSizer", "erlang-wx"},
{"wxStaticLine", "erlang-wx"},
{"wxStaticText", "erlang-wx"},
{"wxStatusBar", "erlang-wx"},
{"wxStdDialogButtonSizer", "erlang-wx"},
{"wxStyledTextCtrl", "erlang-wx"},
{"wxStyledTextEvent", "erlang-wx"},
{"wxSysColourChangedEvent", "erlang-wx"},
{"wxSystemOptions", "erlang-wx"},
{"wxSystemSettings", "erlang-wx"},
{"wxTaskBarIcon", "erlang-wx"},
{"wxTaskBarIconEvent", "erlang-wx"},
{"wxTextAttr", "erlang-wx"},
{"wxTextCtrl", "erlang-wx"},
{"wxTextDataObject", "erlang-wx"},
{"wxTextEntryDialog", "erlang-wx"},
{"wxToggleButton", "erlang-wx"},
{"wxToolBar", "erlang-wx"},
{"wxToolTip", "erlang-wx"},
{"wxToolbook", "erlang-wx"},
{"wxTopLevelWindow", "erlang-wx"},
{"wxTreeCtrl", "erlang-wx"},
{"wxTreeEvent", "erlang-wx"},
{"wxTreebook", "erlang-wx"},
{"wxUpdateUIEvent", "erlang-wx"},
{"wxWebView", "erlang-wx"},
{"wxWebViewEvent", "erlang-wx"},
{"wxWindow", "erlang-wx"},
{"wxWindowCreateEvent", "erlang-wx"},
{"wxWindowDC", "erlang-wx"},
{"wxWindowDestroyEvent", "erlang-wx"},
{"wxXmlResource", "erlang-wx"},
{"wx_misc", "erlang-wx"},
{"wx_object", "erlang-wx"},
{"wxe_master", "erlang-wx"},
{"wxe_server", "erlang-wx"},
{"wxe_util", "erlang-wx"},
{"xmerl", "erlang-xmerl"},
{"xmerl_b64Bin", "erlang-xmerl"},
{"xmerl_b64Bin_scan", "erlang-xmerl"},
{"xmerl_eventp", "erlang-xmerl"},
{"xmerl_html", "erlang-xmerl"},
{"xmerl_lib", "erlang-xmerl"},
{"xmerl_otpsgml", "erlang-xmerl"},
{"xmerl_regexp", "erlang-xmerl"},
{"xmerl_sax_old_dom", "erlang-xmerl"},
{"xmerl_sax_parser", "erlang-xmerl"},
{"xmerl_sax_parser_latin1", "erlang-xmerl"},
{"xmerl_sax_parser_list", "erlang-xmerl"},
{"xmerl_sax_parser_utf16be", "erlang-xmerl"},
{"xmerl_sax_parser_utf16le", "erlang-xmerl"},
{"xmerl_sax_parser_utf8", "erlang-xmerl"},
{"xmerl_sax_simple_dom", "erlang-xmerl"},
{"xmerl_scan", "erlang-xmerl"},
{"xmerl_sgml", "erlang-xmerl"},
{"xmerl_simple", "erlang-xmerl"},
{"xmerl_text", "erlang-xmerl"},
{"xmerl_ucs", "erlang-xmerl"},
{"xmerl_uri", "erlang-xmerl"},
{"xmerl_validate", "erlang-xmerl"},
{"xmerl_xlate", "erlang-xmerl"},
{"xmerl_xml", "erlang-xmerl"},
{"xmerl_xml_indent", "erlang-xmerl"},
{"xmerl_xpath", "erlang-xmerl"},
{"xmerl_xpath_lib", "erlang-xmerl"},
{"xmerl_xpath_parse", "erlang-xmerl"},
{"xmerl_xpath_pred", "erlang-xmerl"},
{"xmerl_xpath_scan", "erlang-xmerl"},
{"xmerl_xs", "erlang-xmerl"},
{"xmerl_xsd", "erlang-xmerl"},
{"xmerl_xsd_type", "erlang-xmerl"},
 {"erlang", "erlang-base"}]).

% The erlang packages list (suffixes only)
-define(PACKAGES, ["dev", "nox", "x11", "asn1", "common-test", "crypto", "debugger", "dialyzer", "diameter", "edoc", "eldap", "et", "eunit", "ftp", "inets", "jinterface", "megaco", "mnesia", "observer", "odbc", "os-mon", "parsetools", "public-key", "reltool", "runtime-tools", "snmp", "ssh", "ssl", "syntax-tools", "tftp", "tools", "wx", "xmerl"]).

% main/1 --
%
%	Generate debhelper substitution variables for Erlang-dependent
%	packages.
%
% Arguments:
%	Options		List of debhelper options (-v, -a, -i, -p*, -N*) or -h.
%
% Result:
%	None.
%
% Side effects:
%	For each of the selected packages the corresponding file
%	debian/package.substvars is created (if necessary) and filled by erlang
%	dependencies. If -h or --help is among arguments then the usage info is
%	printed instead and script is halted.

main(Options) ->
    {Verbosity, TmpDir, Exclude, NewOptions} =
	lists:foldl(fun(Opt, {Sum, Dir, Ex, Opts}) ->
			case Opt of
			    "-h" ->
				usage(),
				halt(2);
			    "--help" ->
				usage(),
				halt(2);
			    "-v" ->
				{Sum + 1, Dir, Ex, Opts};
			    "--verbose" ->
				{Sum + 1, Dir, Ex, Opts};
			    "--ignore=" ++ File ->
				{Sum, Dir, Ex ++ [File], Opts};
			    "-P" ++ D ->
				{Sum, D, Ex, Opts};
			    "--tmpdir=" ++ D ->
				{Sum, D, Ex, Opts};
			    _ ->
				{Sum, Dir, Ex, Opts ++ [Opt]}
			end
		    end, {0, [], [], []}, Options),
    lists:foreach(
      fun({Package, Variables}) ->
	    PkgDir = case TmpDir of
			 [] ->
		    	     filename:join("debian", Package);
			 _ ->
		    	     TmpDir
		     end,
	    delsubstvar(Verbosity, Package, "erlang:Depends"),
	    Variables2 = Variables ++
		case lists:member("erlang:Depends", Variables) of
		    true ->
			Deps = ordsets:to_list(
				 lists:foldl(
				   fun(M, Acc) ->
					case lists:keysearch(M, 1, ?MODULES) of
					    {value, {_, P}} ->
						ordsets:add_element(P, Acc);
					    _ ->
						io:format("WARNING: Module ~s not found~n", [M]),
						Acc
					end
				   end, ordsets:new(),
				   get_remote_modules(Verbosity, PkgDir, Exclude))),
			Dep = join(lists:map(
				     fun(D) ->
					    "${" ++ D ++ ":Depends}"
				     end, Deps), ", "),
			addsubstvar(Verbosity, Package, "erlang:Depends", Dep),
			lists:map(fun(D) ->
					D ++ ":Depends"
				  end, Deps);
		    _ ->
			[]
		end,
	    deladdsubstvar(Verbosity, Package, Variables2, "erlang-abi:Depends",
			   "erlang-abi (= " ++ ?ABI_VERSION ++ ")"),
	    deladdsubstvar(Verbosity, Package, Variables2, "erlang-pcre:Depends",
			   "erlang-pcre (= " ++ ?PCRE_VERSION ++ ")"),
	    deladdsubstvar(Verbosity, Package, Variables2, "erlang-base:Depends",
			   "erlang-base (>= " ++ ?VERSION ++ ")"),
	    lists:foreach(
	      fun(Pkg) ->
		    deladdsubstvar(Verbosity, Package, Variables2, "erlang-" ++ Pkg ++ ":Depends",
				   "erlang-" ++ Pkg ++ " (>= " ++ ?VERSION ++ ")")
	      end, ?PACKAGES)
      end, get_packages(NewOptions)).

% usage/0 --
%
%	Print a short usage info.
%
% Arguments:
%	None.
%
% Result:
%	ok.
%
% Side effects:
%	Usage is printed to stdout.

usage() ->
    io:format("Usage: erlang-depends [options]~n"
	      "Options:~n"
	      "    -h, --help       Show this help message~n"
	      "    -v, --verbose    Verbose mode~n"
	      "    -a, --arch       Act on architecture dependent packages~n"
	      "    -i, --indep      Act on architecture independent packages~n"
	      "    -ppackage, --package=package~n"
	      "                     Act on package \"package\"~n"
	      "    -Npackage, --no-package=package~n"
	      "                     Do not act on package \"package\"~n"
	      "    -Ptmpdir, --tmpdir=tmpdir~n"
	      "                     Use \"tmpdir\" for package build directory~n").

% get_remote_modules/3 --
%
%	Return a difference between all modules used in the application and
%	the local modules which dependencies are satisfied automagically.
%
% Arguments:
%	Verbosity   Verbosity level (0 - silence, 1 - print action).
%	Dir	    Directory where the local BEAM files are to be searched.
%	Exclude	    Don't take into account files in this list.
%
% Result:
%	The list of remote modules.
%
% Side effects:
%	Application files are taken from filesystem.

get_remote_modules(Verbosity, Dir, Exclude) ->
    Mods = ordsets:to_list(ordsets:subtract(get_modules(Dir, Exclude),
					    get_local_modules(Dir, Exclude))),
    if  Verbosity >= 1 ->
	    lists:foreach(fun(M) ->
				io:format("Remote module: ~s~n", [M])
			  end, Mods);
	true ->
	    ok
    end,
    Mods.

% get_modules/2 --
%
%	Return an ordset of all modules found in the application.
%
% Arguments:
%	Dir	    Directory where the app BEAM files are to be searched.
%	Exclude	    Don't take into account files in this list.
%
% Result:
%	The ordset of all used modules.
%
% Side effects:
%	Application files are taken from filesystem.

get_modules(Dir, Exclude) ->
    Modules = lists:map(fun({M, _F, _A}) ->
			    atom_to_list(M)
			end, get_imports(Dir, Exclude)),
    ordsets:from_list(Modules).

% get_local_modules/2 --
%
%	Return an ordset of local modules found in the application (it is
%	constructed from BEAM filenames).
%
% Arguments:
%	Dir	    Directory where the app BEAM files are to be searched.
%	Exclude	    Don't take into account files in this list.
%
% Result:
%	The ordset of all local modules.
%
% Side effects:
%	Files are taken from filesystem.

get_local_modules(Dir, Exclude) ->
    Files = lists:filter(fun(File) ->
				case lists:member(File, Exclude) of
				    true ->
					false;
				    _ ->
					true
				end
			 end, files(Dir, ".*\\.beam$", true)),
    Basenames = lists:map(fun(File) ->
				filename:basename(File, ".beam")
			  end, Files),
    ordsets:from_list(Basenames).

% get_imports/2 --
%
%	Get imports from all BEAM files in the specified directory and below.
%
% Arguments:
%	Dir	    Directory where to search for BEAM files
%	Exclude	    Don't take into account files in this list.
%
% Results:
%	A list of imports from all found BEAM files.
%
% Side effects:
%	Files are taken from filesystem.

get_imports(Dir, Exclude) ->
    Files = lists:filter(fun(File) ->
				case lists:member(File, Exclude) of
				    true ->
					false;
				    _ ->
					true
				end
			 end, files(Dir, ".*\\.beam$", true)),
    lists:foldl(fun(File, Acc) ->
			case beam_lib:chunks(File, [imports]) of
			    {ok, {_, [{imports, List}]}} ->
				Acc ++ List;
			    _ ->
				Acc
			end
		end, [], Files).

% split/2 --
%
%	Split string into a list of tokens using the specified delimiter
%
% Arguments:
%	String	    String to split
%	Delimiter   Character (delimiter)
%
% Results:
%	A list of strings.
%
% Side effects:
%	None.

split(String, Delimiter) ->
    split(String, Delimiter, none, []).

split([], _Delimiter, Current, Res) ->
    case Current of
	none ->
	    lists:reverse(Res);
	_ ->
	    lists:reverse([lists:reverse(Current) | Res])
    end;

split([Delimiter | Tail], Delimiter, Current, Res) ->
    case Current of
	none ->
	    split(Tail, Delimiter, [], [[] | Res]);
	_ ->
	    split(Tail, Delimiter, [], [lists:reverse(Current) | Res])
    end;

split([Char | Tail], Delimiter, Current, Res) ->
    case Current of
	none ->
	    split(Tail, Delimiter, [Char], Res);
	_ ->
	    split(Tail, Delimiter, [Char | Current], Res)
    end.

% join/2 --
%
%	Join string list into a single string using the specified delimiter
%
% Arguments:
%	List	    List of strings to join
%	Delimiter   Character or character list (delimiter)
%
% Results:
%	A string.
%
% Side effects:
%	None.

join(List, Delimiter) ->
    join(List, Delimiter, []).

join([], _Delimiter, Res) ->
    lists:flatten(lists:reverse(Res));

join([String | Tail], Delimiter, []) ->
    join(Tail, Delimiter, [String]);

join([String | Tail], Delimiter, Res) ->
    join(Tail, Delimiter, [String, Delimiter | Res]).

% delsubstvar/3 --
%
%	Removes substitution variable from a substvar file for a given
%	package in debian/ directory.
%
% Arguments:
%	Verbosity   Verbosity level (0 - silence, 1 - print action)
%	Package	    Name of a package (file Package ++ ".substvars" is used).
%	Substvar    Name of a substitution variable to delete.
%
% Results:
%	ok or halt.
%
% Side effects:
%	File "debian/" ++ Package ++ ".substvars" is overwritten. The
%	specified variable is deleted. Program is halted in case of error.

delsubstvar(Verbosity, Package, Substvar) ->
    SubstvarFile = filename:join("debian", Package ++ ".substvars"),
    if  Verbosity >= 1 ->
	    io:format("Deleting substvar ~s from file ~s~n", [Substvar, SubstvarFile]);
	true ->
	    ok
    end,
    case file:read_file(SubstvarFile) of
	{ok, BinData} ->
	    StrData = binary_to_list(BinData),

	    % Remove the trailing newline if any

	    Len = string:len(StrData),
	    StrData2 = case Len - string:rstr(StrData, "\n") of
			    0 when Len > 0 ->
				string:left(StrData, Len - 1);
			    _ ->
				StrData
		       end,
	    Tokens = split(StrData2, $\n),
	    NewTokens = lists:filter(
			    fun(S) ->
				    case string:str(S, Substvar ++ "=") of
					1 ->
					    false;
					_ ->
					    true
				    end
			    end, Tokens),
	    case file:write_file(SubstvarFile, join(NewTokens, $\n) ++ "\n") of
		ok ->
		    ok;
		{error, Error} ->
		    io:format("ERROR: Can't write ~s: ~s~n", [SubstvarFile, Error]),
		    halt(1)
	    end;
	{error, enoent} ->
	    ok;
	{error, Error} ->
	    io:format("ERROR: Can't read ~s: ~s~n", [SubstvarFile, Error]),
	    halt(1)
    end.

% addsubstvar/4 --
%
%	Adds a dependency to a substitution variable in a substvar file
%	for a given package in debian/ directory.
%
% Arguments:
%	Verbosity   Verbosity level (0 - silence, 1 - print action)
%	Package	    Name of a package (file Package ++ ".substvars" is used).
%	Substvar    Name of a substitution variable to add/change.
%	Dependency  An added substitution dependency string.
%
% Results:
%	ok or halt.
%
% Side effects:
%	File "debian/" ++ Package ++ ".substvars" is overwritten. The specified
%	depandency string is added to the variable. Program is halted in case
%	of error.

addsubstvar(Verbosity, Package, Substvar, Dependency) ->
    SubstvarFile = filename:join("debian", Package ++ ".substvars"),
    if  Verbosity >= 1 ->
	    io:format("Adding value ~s to substvar ~s in file ~s~n",
		      [Substvar, Dependency, SubstvarFile]);
	true ->
	    ok
    end,
    case file:read_file(SubstvarFile) of
	{ok, BinData} ->
	    StrData = binary_to_list(BinData),

	    % Remove the trailing newline if any

	    Len = string:len(StrData),
	    StrData2 = case Len - string:rstr(StrData, "\n") of
			    0 when Len > 0 ->
				string:left(StrData, Len - 1);
			    _ ->
				StrData
		       end,
	    Tokens = split(StrData2, $\n),
	    {NewTokens, Found} = lists:mapfoldl(
				    fun(S, F) ->
					    case string:str(S, Substvar ++ "=") of
						1 ->
						    {S ++ ", " ++ Dependency, true};
						_ ->
						    {S, F}
					    end
				    end, false, Tokens),
	    NewTokens2 = if Found ->
				NewTokens;
			    true ->
				[Substvar ++ "=" ++ Dependency | NewTokens]
			 end,
	    case file:write_file(SubstvarFile, join(NewTokens2, $\n) ++ "\n") of
		ok ->
		    ok;
		{error, Error} ->
		    io:format("Can't write ~s: ~s~n", [SubstvarFile, Error]),
		    halt(1)
	    end;
	{error, enoent} ->
	    case file:write_file(SubstvarFile, [Substvar, "=", Dependency, "\n"]) of
		ok ->
		    ok;
		{error, Error} ->
		    io:format("Can't write ~s: ~s~n", [SubstvarFile, Error]),
		    halt(1)
	    end;
	{error, Error} ->
	    io:format("Can't read ~s: ~s~n", [SubstvarFile, Error]),
	    halt(1)
    end.

% deladdsubstvar/5 --
%
%	Delete a substitution variable from a substvar file and add a
%	dependency to it if this substvar is present in a specified list of
%	variables for a given package in debian/ directory.
%
% Arguments:
%	Verbosity   Verbosity level (0 - silence, 1 - print action)
%	Package	    Name of a package (file Package ++ ".substvars" is used).
%	Variables   List of requested variables for the package.
%	Substvar    Name of a substitution variable to add/change.
%	Dependency  An added substitution dependency string.
%
% Results:
%	ok or halt.
%
% Side effects:
%	File "debian/" ++ Package ++ ".substvars" is overwritten. The specified
%	dependency string is either deleted or replaced. Program is halted in
%	case of error.

deladdsubstvar(Verbosity, Package, Variables, Substvar, Dependency) ->
    delsubstvar(Verbosity, Package, Substvar),
    case lists:member(Substvar, Variables) of
	true ->
	    addsubstvar(Verbosity, Package, Substvar, Dependency);
	_ ->
	    ok
    end.

% get_packages/1 --
%
%	Parses debhelper command line options and debian/control file and
%	returns packages with requested substvars to act on.
%
% Arguments:
%	ArgList	    Dephelper options (only -a, -i, -p, -N options are
%		    recognised).
%
% Results:
%	{ok, [{Package,Vars}]} to work on or error message and halt if
%	debian/control is unreadable or unknown option is specified.
%
% Side effects:
%	Program is halted in case of error, packages info is taken from
%	an external file.

get_packages(ArgList) ->
    ControlFile = filename:join("debian", "control"),
    case file:read_file(ControlFile) of
	{ok, BinData} ->
	    {Arches, Excluded, Explicit} =
		lists:foldl(fun(Arg, {A1, E1, E2}) ->
				case Arg of
				    % Only the last -a or -i option takes
				    % effect

				    "-a" ->
					{arch, E1, E2};
				    "--arch" ->
					{arch, E1, E2};
				    "-i" ->
					{indep, E1, E2};
				    "--indep" ->
					{indep, E1, E2};
				    "-s" ->
					io:format("Options -s and --same-arch aren't supported yet~n"),
					halt(1);
				    "--same-arch" ->
					io:format("Options -s and --same-arch aren't supported yet~n"),
					halt(1);
				    "-p" ++ Package ->
					{A1, E1, E2 ++ [Package]};
				    "--package=" ++ Package ->
					{A1, E1, E2 ++ [Package]};
				    "-N" ++ Package ->
					{A1, E1 ++ [Package], E2};
				    "--no-package=" ++ Package ->
					{A1, E1 ++ [Package], E2};
				    _ ->
					io:format("Unknown option ~s~n", [Arg]),
					halt(1)
				end
			    end, {all, [], []}, ArgList),

	    % Join up continuation lines

	    StrData = re:replace(BinData, "\\n( |\\t)", "\\1", [global, {return, list}]),

	    % Add an extra empty line for the case if debian/config doesn't have a trailing LF

	    Tokens = split(StrData, $\n) ++ [[]],
	    {_Arch, _Package, _Vars, Packages, AllPackages} =
		lists:foldl(fun(Line, {A, P, Vs, Ps, APs}) ->
				case Line of
				    "Package: " ++ Pkg ->
					{A, string:strip(Pkg), Vs, Ps, APs};
				    "Architecture: " ++ Arc ->
					{string:strip(Arc), P, Vs, Ps, APs};
				    "Pre-Depends: " ++ Deps ->
					{A, P, Vs ++ find_vars(Deps), Ps, APs};
				    "Depends: " ++ Deps ->
					{A, P, Vs ++ find_vars(Deps), Ps, APs};
				    "Recommends: " ++ Deps ->
					{A, P, Vs ++ find_vars(Deps), Ps, APs};
				    "Suggests: " ++ Deps ->
					{A, P, Vs ++ find_vars(Deps), Ps, APs};
				    "Enhances: " ++ Deps ->
					{A, P, Vs ++ find_vars(Deps), Ps, APs};
				    "Breaks: " ++ Deps ->
					{A, P, Vs ++ find_vars(Deps), Ps, APs};
				    "Conflicts: " ++ Deps ->
					{A, P, Vs ++ find_vars(Deps), Ps, APs};
				    "Provides: " ++ Deps ->
					{A, P, Vs ++ find_vars(Deps), Ps, APs};
				    "Replaces: " ++ Deps ->
					{A, P, Vs ++ find_vars(Deps), Ps, APs};
				    "" ->
					case P of
					    "" ->
						% Two LF in a row or the end of a source package

						{"", "", [], Ps, APs};
					    _ ->
						case lists:member(P, Excluded) of
						    true ->
							% The package is excluded by -Npackage

							{"", "", [], Ps, APs};
						    _ ->
							case lists:member(P, Explicit) of
							    true ->
								% The package is explicitly required

								{"", "", [], Ps ++ [{P, Vs}], APs};
							    _ ->
								case A of
								    "all" ->
									case Arches of
									    indep ->
										% Arch independent packages
										% are requested

										{"", "", [], Ps ++ [{P, Vs}], APs};
									    all ->
										{"", "", [], Ps, APs ++ [{P, Vs}]};
									    _ ->
										{"", "", [], Ps, APs}
									end;
								    _ ->
									case Arches of
									    arch ->
										% Arch dependent packages
										% are requested

										{"", "", [], Ps ++ [{P, Vs}], APs};
									    all ->
										{"", "", [], Ps, APs ++ [{P, Vs}]};
									    _ ->
										{"", "", [], Ps, APs}
									end
								end
							end
						end
					end;
				    _ ->
					{A, P, Vs, Ps, APs}
				end
			    end, {"", "", [], [], []}, Tokens),
	    case {Arches, Packages} of
		{all, []} ->
		    % There aren't explicitly requested packages

		    AllPackages;
		_ ->
		    Packages
	    end;
	{error, Error} ->
	    io:format("Can't read ~s: ~s~n", [ControlFile, Error]),
	    halt(1)
    end.

% find_vars/1 --
%
%	Find substitution variables in dependencies line and return list of
%	their names.
%
% Arguments:
%	Dependencies	Dependencies line from debian/control
%
% Result:
%	List of substvars names (inside ${}).
%
% Side effects:
%	None.

find_vars(Dependencies) ->
    case re:run(Dependencies, "\\$\\{(\\S*)\\}", [global, {capture, all_but_first, list}]) of
	{match, Captured} ->
	    lists:foldl(fun(M, Acc) ->
			    Acc ++ M
			end, [], Captured);
	_ ->
	    []
    end.

% files/3 --
%
%	Return all files in a directory which names match a given expression.
%	(This procedure is borrowed from http://erlang.org/examples/examples-2.0.html
%	and a bit modified.)
%
% Arguments:
%	Dir	    Directory from which to search
%	Re	    Regular expression for filename matching
%	Recursive   Whether to search for files recursively
%
% Result:
%	A list of filenames.
%
% Side effects:
%	File and directory names are taken from filesystem.

files(Dir, Re, Recursive) ->
    find_files(Dir, Re, Recursive, []).

% find_files/4 --
%
%	Find all files in a directory which names match a given expression,
%	prepend them to a given list of files and return the total files list.
%	(This procedure is borrowed from http://erlang.org/examples/examples-2.0.html
%	and a bit modified.)
%
% Arguments:
%	Dir	    Directory from which to search
%	Re	    Regular expression for filename matching
%	Recursive   Whether to search for files recursively
%	L	    List of already found files
%
% Result:
%	A list of filenames.
%
% Side effects:
%	File and directory names are taken from filesystem.

find_files(Dir, Re, Recursive, L) ->
    case file:list_dir(Dir) of
	{ok, Files} ->
	    find_files(Files, Dir, Re, Recursive, L);
	{error, _} ->
	    L
    end.

% find_files/5 --
%
%	Check all specified filenames if they match a given expressions and
%	prepend matched ones to a given list of filenames. If the file type is
%	directory and search is recursive then descend into it and add found
%	filenames to the result too. Return the total files list.
%	(This procedure is borrowed from http://erlang.org/examples/examples-2.0.html
%	and a bit modified.)
%
% Arguments:
%	_FL	    List of files in directory Dir
%	Dir	    Directory from which to search
%	Re	    Regular expression for filename matching
%	Recursive   Whether to search for files recursively
%	L	    List of already found files
%
% Result:
%	A list of filenames.
%
% Side effects:
%	File and directory names are taken from filesystem.

find_files(_FL = [File | T], Dir, Re, Recursive, L) ->
    FullName = filename:join(Dir, File),
    case file_type(FullName) of
	regular ->
	    case re:run(FullName, Re) of
		{match, _}  ->
		    find_files(T, Dir, Re, Recursive, [FullName | L]);
		_ ->
		    find_files(T, Dir, Re, Recursive, L)
	    end;
	directory ->
	    case Recursive of
		true ->
		    L1 = find_files(FullName, Re, Recursive, L),
		    find_files(T, Dir, Re, Recursive, L1);
		false ->
		    find_files(T, Dir, Re, Recursive, L)
	    end;
	error ->
	    find_files(T, Dir, Re, Recursive, L)
    end;

find_files([], _, _, _, L) ->
    L.

% file_type/1 --
%
%	Return file type (regular, directory, or error) for a given filename.
%	(This procedure is borrowed from http://erlang.org/examples/examples-2.0.html
%	and a bit modified.)
%
% Arguments:
%	File	    Filename to get type.
%
% Result:
%	A file type.
%
% Side effects:
%	File info is taken from the filesystem.

file_type(File) ->
    case file:read_file_info(File) of
	{ok, FileInfo} ->
	    case FileInfo#file_info.type of
		regular ->
		    regular;
		directory ->
		    directory;
		_ ->
		    error
	    end;
	_ ->
	    error
    end.

% vim:ft=erlang
