anchor.diff:  
   %% @private
   -spec parse_config([{term(), term()}], [{atom(), term()}], [{atom(), term()}],
  -                   parse_spec(), map|list) ->
  +                   syntax(), parse_opts()) ->
       {ok, [{atom(), term()}], [{atom(), term()}]}.
   
  -parse_config([], Opts1, Opts2, _Spec, list) ->
  -    {ok, lists:reverse(Opts1), lists:reverse(Opts2)};
  -
  -parse_config([], Opts1, Opts2, _Spec, map) ->
  +parse_config([], Ok, NoOk, _Syntax, #{return:=map}) ->
       % We need to reverse to get only the last value
  -    {ok, maps:from_list(lists:reverse(Opts1)), maps:from_list(lists:reverse(Opts2))};
  -
  -parse_config([{Key, Val}|Rest], Opts1, Opts2, Spec, Type) ->
  +    {ok, maps:from_list(lists:reverse(Ok)), maps:from_list(lists:reverse(NoOk))};
  +
  +parse_config([], Ok, NoOk, _Syntax, _) ->
  +    {ok, lists:reverse(Ok), lists:reverse(NoOk)};
  +
  +parse_config([{Key, Val}|Rest], Ok, NoOk, Syntax, Opts) ->
       case is_atom(Key) of
           true ->
  -            find_config(Key, Key, Val, Rest, Opts1, Opts2, Spec, Type);
  +            find_config(Key, Key, Val, Rest, Ok, NoOk, Syntax, Opts);
           _ ->
  -            case catch to_atom(Key) of
  -                {invalid_atom, _} ->
  -                    parse_config(Rest, Opts1, [{Key, Val}|Opts2], Spec, Type);
  +            case catch to_existing_atom(Key) of
  +                {unknown_atom, _} ->
  +                    parse_config(Rest, Ok, [{Key, Val}|NoOk], Syntax, Opts);
                   Index -> 
  -                    find_config(Index, Key, Val, Rest, Opts1, Opts2, Spec, Type)
  +                    find_config(Index, Key, Val, Rest, Ok, NoOk, Syntax, Opts)
               end
       end;
   
  -parse_config([Key|Rest], Opts1, Opts2, Spec, Type) ->
  -    parse_config([{Key, true}|Rest], Opts1, Opts2, Spec, Type).
  -
  -
  -%% @private
  -find_config(Index, Key, Val, Rest, Opts1, Opts2, Spec, Type) ->
  -    case maps:get(Index, Spec, not_found) of
  +parse_config([Key|Rest], Ok, NoOk, Syntax, Opts) ->
  +    parse_config([{Key, true}|Rest], Ok, NoOk, Syntax, Opts).
  +
  +
  +%% @private
  +find_config(AtomKey, Key, Val, Rest, Ok, NoOk, Syntax, Opts) ->
  +    case maps:get(AtomKey, Syntax, not_found) of
           not_found ->
  -            parse_config(Rest, Opts1, [{Key, Val}|Opts2], Spec, Type);
  +            parse_config(Rest, Ok, [{Key, Val}|NoOk], Syntax, Opts);
           Fun when is_function(Fun, 3) ->
  -            case catch Fun(Index, Val, Opts1) of
  +            case catch Fun(AtomKey, Val, Ok) of
                   ok ->
  -                    parse_config(Rest, [{Index, Val}|Opts1], Opts2, Spec, Type);
  +                    parse_config(Rest, [{AtomKey, Val}|Ok], NoOk, Syntax, Opts);
                   {ok, Val1} ->
  -                    parse_config(Rest, [{Index, Val1}|Opts1], Opts2, Spec, Type);
  -                {ok, Key1, Val1} ->
  -                    parse_config(Rest, [{Key1, Val1}|Opts1], Opts2, Spec, Type);
  -                {opts, Opts1B} ->
  -                    parse_config(Rest, Opts1B, Opts2, Spec, Type);
  +                    parse_config(Rest, [{AtomKey, Val1}|Ok], NoOk, Syntax, Opts);
  +                {ok, AtomKey1, Val1} when is_atom(AtomKey1) ->
  +                    parse_config(Rest, [{AtomKey1, Val1}|Ok], NoOk, Syntax, Opts);
  +                {new_ok, OkB} ->
  +                    parse_config(Rest, OkB, NoOk, Syntax, Opts);
                   error ->
  -                    throw({invalid_key, Index});
  +                    throw({invalid_key, AtomKey});
                   {error, Error} ->
  -                    throw(Error)
  +                    throw(Error);
  +                {'EXIT', Error} ->
  +                    throw({internal_error, ?MODULE, ?LINE, Error})
               end;
  -        SubSpec when is_map(SubSpec) ->
  +        SubSyntax when is_map(SubSyntax) ->
               case is_list(Val) orelse is_map(Val) of
                   true ->
  -                    case parse_config(Val, SubSpec, Type) of
  -                        {ok, Val1, _SubOpts2} ->
  -                            parse_config(Rest, [{Index, Val1}|Opts1], Opts2, Spec, Type);
  +                    case parse_config(Val, SubSyntax, Opts) of
  +                        {ok, Val1, _SubNoOk} ->
  +                            parse_config(Rest, [{AtomKey, Val1}|Ok], NoOk, Syntax, Opts);
                           {error, Term} ->
                               throw(Term)
                       end;
                   false ->
  -                    throw({invalid_key, Index})
  +                    throw({invalid_key, AtomKey})
               end;
  -        {update, UpdType, Index2, Key2, SubSpec} ->
  -            case do_parse_config(SubSpec, Val) of
  +        {update, UpdType, Index2, Key2, SubSyntax} ->
  +            case do_parse_config(SubSyntax, Val) of
                   {ok, Val2} ->
  -                    NewOpts1 = case lists:keytake(Index2, 1, Opts1) of
  +                    NewOk = case lists:keytake(Index2, 1, Ok) of
                           false when UpdType==map -> 
  -                            [{Index2, maps:put(Key2, Val2, #{})}|Opts1];
  +                            [{Index2, maps:put(Key2, Val2, #{})}|Ok];
                           false when UpdType==list -> 
  -                            [{Index2, [{Key2, Val2}]}|Opts1];
  -                        {value, {Index2, Base}, Opts1A} when UpdType==map ->
  -                            [{Index2, maps:put(Key2, Val2, Base)}|Opts1A];
  -                        {value, {Index2, Base}, Opts1A} when UpdType==list ->
  -                            [{Index2, [{Key2, Val2}|Base]}|Opts1A]
  +                            [{Index2, [{Key2, Val2}]}|Ok];
  +                        {value, {Index2, Base}, OkA} when UpdType==map ->
  +                            [{Index2, maps:put(Key2, Val2, Base)}|OkA];
  +                        {value, {Index2, Base}, OkA} when UpdType==list ->
  +                            [{Index2, [{Key2, Val2}|Base]}|OkA]
                       end,
  -                    parse_config(Rest, NewOpts1, Opts2, Spec, Type);
  +                    parse_config(Rest, NewOk, NoOk, Syntax, Opts);
                   error ->
  -                    throw({invalid_key, Index})
  +                    throw({invalid_key, AtomKey})
               end;
  -        KeySpec ->
  -            case do_parse_config(KeySpec, Val) of
  +        SyntaxOp ->
  +            case do_parse_config(SyntaxOp, Val) of
                   {ok, Val1} ->
  -                    parse_config(Rest, [{Index, Val1}|Opts1], Opts2, Spec, Type);
  +                    parse_config(Rest, [{AtomKey, Val1}|Ok], NoOk, Syntax, Opts);
                   error ->
  -                    throw({invalid_key, Index})
  +                    throw({invalid_key, AtomKey})
               end
       end.
   
   
   %% @private
  -to_atom(Term) when is_atom(Term) ->
  +to_existing_atom(Term) when is_atom(Term) ->
       Term;
   
  -to_atom(Term) ->
  +to_existing_atom(Term) ->
       case catch list_to_existing_atom(nklib_util:to_list(Term)) of
  -        {'EXIT', _} -> throw({invalid_atom, Term});
  +        {'EXIT', _} -> throw({unknown_atom, Term});
           Atom -> Atom
       end.
   
   
   
   %% @private
  --spec do_parse_config(parse_opt(), term()) ->
  +-spec do_parse_config(syntax_opt(), term()) ->
       {ok, term()} | error.
   
   do_parse_config(any, Val) ->
       {ok, Val};
   
   do_parse_config(atom, Val) ->
  -    {ok, to_atom(Val)};
  +    {ok, to_existing_atom(Val)};
   
   do_parse_config(boolean, Val) when Val==0; Val=="0" ->
       {ok, false};
  
positive.code:     ets:update_counter(?MODULE, {Mod, Domain, Key}, Count).
  
  
  %% @doc Parses a list of options
  %% For lists, if duplicated entries, the last one wins
  -spec parse_config(map()|list(), parse_spec()) ->
      {ok, [{atom(), term()}], [{atom(), term()}]} | 
      {ok, map(), map()} |
      {error, term()}.
  
  parse_config(Terms, Spec) ->
      parse_config(Terms, Spec, list).
  
  
  %% @doc Parses a list of options
  -spec parse_config(map()|list(), parse_spec(), map|list) ->
      {ok, [{atom(), term()}], [{atom(), term()}]} | 
      {ok, map(), map()} |
      {error, term()}.
  
  parse_config([], _Spec, list) ->
      {ok, [], []};
  
  parse_config([], _Spec, map) ->
      {ok, #{}, #{}};
  
  
  parse_config(Terms, Spec, Type) when is_list(Terms) ->
      try
          parse_config(Terms, [], [], Spec, Type)
      catch
          throw:Throw -> {error, Throw}
      end;
  
  parse_config(Terms, Spec, Type) when is_map(Terms) ->
      case maps:size(Terms) of
          0 when Type==list -> {ok, [], []};
          0 when Type==map -> {ok, #{}, #{}};
          _ -> parse_config(maps:to_list(Terms), Spec, Type)
      end.
  
  
  %% @doc Loads parsed application environment
  -spec load_env(term(), atom(), map()|list(), parse_spec()) ->
      ok | {error, term()}.
  
  load_env(Mod, App, Defaults, Spec) ->
      AppEnv = application:get_all_env(App),
      Env1 = nklib_util:defaults(AppEnv, nklib_util:to_list(Defaults)),
      case parse_config(Env1, Spec) of
          {ok, Opts, _} ->
              lists:foreach(fun({K,V}) -> put(Mod, K, V) end, Opts),
              ok;
  
negative.code:     end;
  
  do_parse_config({enum, List}, Val) ->
      Atom = to_existing_atom(Val),
      case lists:member(Atom, List) of
          true -> {ok, Atom};
          false -> error
  