anchor.diff:  find_default_out_dir({_Mod, _S}) -> ".";
   find_default_out_dir(File) -> filename:dirname(File).
   
  -%% @spec proto_defs(Mod, Defs) -> CompRet
   %% @equiv proto_defs(Mod, Defs, [])
  +-spec proto_defs(module(), gpb_parse:defs()) -> comp_ret().
   proto_defs(Mod, Defs) ->
       proto_defs(Mod, Defs, []).
   
  -%% @spec proto_defs(Mod, Defs, Opts) -> CompRet
  -%%            Mod  = atom()
  -%%            Defs = [Def]
  -%%            Def = {{enum, EnumName}, Enums} |
  -%%                  {{msg, MsgName}, MsgFields}
  -%%            EnumName = atom()
  -%%            Enums = [{Name, integer()}]
  -%%            Name = atom()
  -%%            MsgName = atom()
  -%%            MsgFields = [#field{}]
  -%%
   %% @doc
   %% Compile a list of pre-parsed definitions to file or to a binary.
   %% See {@link file/2} for information on options and return values.
  +-spec proto_defs(module(), gpb_parse:defs(), opts()) -> comp_ret().
   proto_defs(Mod, Defs, Opts) ->
       do_proto_defs_aux1(Mod, Defs, normalize_opts(Opts)).
   
  
positive.code: %% version of Erlang/OTP to generate code for. The default, `current'
  %% means that the generated code is expected to be compiled and run
  %% on the same major version as gpb runs on.
  file(File, Opts) ->
      do_file_or_string(File, Opts).
  
  %% @spec string(Mod, Str) -> CompRet
  %% @equiv string(Mod, Str, [])
  string(Mod, Str) ->
      string(Mod, Str, []).
  
  %% @spec string(Mod, Str, Opts) -> CompRet
  %%     Mod = atom()
  %%     Str = string()
  %%     Opts = list()
  %% @doc
  %% Compile a `.proto' file as string. See {@link file/2} for information
  %% on options and return values.
  string(Mod, Str, Opts) ->
      do_file_or_string({Mod, Str}, Opts).
  
  
negative.code: %% 64 - 7 = 57.
  -define(NB, 57).
  
  %% -- Types -----------------------------------------------------
  
  %% Options
  -type boolean_opt(X) :: X | {X, boolean()}.% Just an option `X' means `{X,true}'
  -type directory() :: string().
  
  -type opts() :: [opt()].
  -type opt() :: boolean_opt(type_specs) |
                 {verify, optionally | always | never} |
                 {copy_bytes, true | false | auto | integer() | float()} |
                 {strings_as_binaries, boolean()} | strings_as_binaries |
                 boolean_opt(defs_as_proplists) |
                 boolean_opt(descriptor) |
                 boolean_opt(maps) |
                 boolean_opt(msgs_as_maps) |
                 boolean_opt(mapfields_as_maps) |
                 boolean_opt(defs_as_maps) |
                 {maps_unset_optional, omitted | present_undefined} |
                 boolean_opt(nif) |
                 {load_nif, string()} |
                 {i, directory()} |
                 {o, directory()} |
                 {o_erl, directory()} | {o_hrl, directory()} |
                 {o_nif_cc, directory()} |
                 binary | to_proto_defs | to_msg_defs |
                 return |
                 boolean_opt(return_warnings) | boolean_opt(return_errors) |
                 report |
                 boolean_opt(report_warnings) | boolean_opt(report_errors) |
                 boolean_opt(warnings_as_errors) |
                 boolean_opt(include_as_lib) |
                 boolean_opt(use_packages) |
                 {erlc_compile_options,string()} |
                 {msg_name_prefix,
                  string() | atom() |
                  {by_proto, [{atom(), string() | atom()}]}} |
                 {msg_name_suffix, string() | atom()} |
                 boolean_opt(msg_name_to_snake_case) |
                 boolean_opt(msg_name_to_lower) |
                 {module_name_prefix, string() | atom()} |
                 {module_name_suffix, string() | atom()} |
                 {any_translate, [translation()]} |
                 boolean_opt(epb_compatibility) |
                 boolean_opt(epb_functions) |
                 boolean_opt(defaults_for_omitted_optionals) |
                 boolean_opt(type_defaults_for_omitted_optionals) |
                 {import_fetcher, import_fetcher_fun()} |
                 {target_erlang_version, integer() | current} |
                 term().
  
  -type translation() :: {encode, mod_fn_argtemplate()} |
                         {decode, mod_fn_argtemplate()} |
                         {merge,  mod_fn_argtemplate()} |
                         {verify, mod_fn_argtemplate()}.
  -type fn_name() :: atom().
  -type mod_fn_argtemplate() :: {module(), fn_name(), arg_template()}.
  -type arg_template() :: [arg()].
  -type arg() :: term() | named_arg().
  -type named_arg() :: '$1' | '$2' | '$errorf' | '$user_data' | '$op'.
  
  -type fetcher_ret() :: from_file | {ok, string()} | {error, term()}.
  -type import_fetcher_fun() :: fun((string()) -> fetcher_ret()).
  
  %% Compilation return values
  -type comp_ret() :: mod_ret() | bin_ret() | error_ret().
  -type mod_ret() :: ok | {ok, [warning()]}.
  -type bin_ret() :: {ok, module(), code()} |
                     {ok, module(), code(), [warning()]}.
  -type error_ret() :: error | {error, reason()} | {error, reason(), [warning()]}.
  -type warning() :: term().
  -type reason() :: term().
  -type code() :: binary() | gpb_parse:defs() | [code_item()].
  -type code_item() :: {erl, ErlCode :: binary()} |
                       {nif, NifCcText :: string()}.
  -export_type([opts/0, opt/0]).
  -export_type([comp_ret/0]).
  
  
  %% @equiv file(File, [])
  -spec file(string()) -> comp_ret().
  file(File) ->
      file(File, []).
  
  %% @doc
  %% Compile a .proto file to a .erl file and to a .hrl file.
  %%
  