aboutsummaryrefslogtreecommitdiffstats
path: root/lib/diameter/src/compiler/diameter_make.erl
diff options
context:
space:
mode:
authorAnders Svensson <[email protected]>2013-09-23 10:31:21 +0200
committerAnders Svensson <[email protected]>2013-11-28 17:27:27 +0100
commit265c88664b93f9069c86bf6c25e5d07b7f41d2dc (patch)
treed5fdb9c37a57108d3e3a14fd2d4089df33923b4f /lib/diameter/src/compiler/diameter_make.erl
parent5682e18c8a31e3c32e9abd41120b2c1ae4c6930f (diff)
downloadotp-265c88664b93f9069c86bf6c25e5d07b7f41d2dc.tar.gz
otp-265c88664b93f9069c86bf6c25e5d07b7f41d2dc.tar.bz2
otp-265c88664b93f9069c86bf6c25e5d07b7f41d2dc.zip
Extend diameter_make:codec/2
Function can now take a literal dictionary as input, instead of a path, and can return results instead of writing them to the filesystem.
Diffstat (limited to 'lib/diameter/src/compiler/diameter_make.erl')
-rw-r--r--lib/diameter/src/compiler/diameter_make.erl105
1 files changed, 80 insertions, 25 deletions
diff --git a/lib/diameter/src/compiler/diameter_make.erl b/lib/diameter/src/compiler/diameter_make.erl
index e4486973dd..c883eb91a9 100644
--- a/lib/diameter/src/compiler/diameter_make.erl
+++ b/lib/diameter/src/compiler/diameter_make.erl
@@ -39,30 +39,40 @@
-export_type([opt/0]).
+%% Options passed to codec/2.
-type opt() :: {include|outdir|name|prefix|inherits, string()}
+ | return
| verbose
| debug.
+%% Literal dictionary or path. A NL of CR identifies the former.
+-type dict() :: iolist()
+ | binary().
+
+%% Name of a literal dictionary if otherwise unspecified.
+-define(DEFAULT_DICT_NAME, "dictionary.dia").
+
%% ===========================================================================
%% codec/1-2
%%
-%% Parse a dictionary file and generate a codec module.
+%% Parse a dictionary file and generate a codec module. Input
+%% dictionary can be either a path or the dictionary itself: the
+%% occurrence of \n or \r in the argument is used to distinguish the
+%% two.
--spec codec(Path, [opt()])
+-spec codec(File, [opt()])
-> ok
+ | {ok, Ret}
| {error, Reason}
- when Path :: string(),
+ when File :: dict(),
+ Ret :: list(), %% [Erl, Hrl | Debug], Debug = [] | [ParseD, Forms]
Reason :: string().
codec(File, Opts) ->
- case dict(File, Opts) of
- {ok, Dict} ->
- make(File,
- Opts,
- Dict,
- lists:append([[dict, forms] || lists:member(debug, Opts)])
- ++ [erl, hrl]);
+ case to_dict(File, Opts) of
+ {ok, {Dict, Dictish}} ->
+ make(file(Dictish), Opts, Dict);
{error, _} = E ->
E
end.
@@ -70,30 +80,63 @@ codec(File, Opts) ->
codec(File) ->
codec(File, []).
+file({path, Path}) ->
+ Path;
+file(_) ->
+ ?DEFAULT_DICT_NAME.
+
%% dict/2
%%
%% Parse a dictionary file and return the orddict that a codec module
%% returns from dict/0.
--spec dict(string(), [opt()])
+-spec dict(File, [opt()])
-> {ok, orddict:orddict()}
- | {error, string()}.
+ | {error, string()}
+ when File :: dict().
-dict(Path, Opts) ->
- case diameter_dict_util:parse({path, Path}, Opts) of
- {ok, _} = Ok ->
- Ok;
- {error = E, Reason} ->
- {E, diameter_dict_util:format_error(Reason)}
+dict(File, Opts) ->
+ case to_dict(File, Opts) of
+ {ok, {Dict, _}} ->
+ {ok, Dict};
+ {error, _} = E ->
+ E
end.
dict(File) ->
dict(File, []).
+%% to_dict/2
+
+to_dict(File, Opts) ->
+ Dictish = maybe_path(File),
+ case diameter_dict_util:parse(Dictish, Opts) of
+ {ok, Dict} ->
+ {ok, {Dict, Dictish}};
+ {error = E, Reason} ->
+ {E, diameter_dict_util:format_error(Reason)}
+ end.
+
+maybe_path(File) ->
+ Bin = iolist_to_binary([File]),
+ case is_path(Bin) of
+ true -> {path, File};
+ false -> Bin
+ end.
+
+%% Interpret anything containing \n or \r as a literal dictionary,
+%% otherwise a path. (Which might be the wrong guess in the worst case.)
+is_path(Bin) ->
+ try
+ [throw(C) || <<C>> <= Bin, $\n == C orelse $\r == C],
+ true
+ catch
+ throw:_ -> false
+ end.
+
%% format/1
%%
-%% Turn an orddict returned by dict/1-2 back into a dictionary file
-%% in the form of an iolist().
+%% Turn an orddict returned by dict/1-2 back into a dictionary.
-spec format(orddict:orddict())
-> iolist().
@@ -108,7 +151,7 @@ format(Dict) ->
-spec reformat(File)
-> {ok, iolist()}
| {error, Reason}
- when File :: string(),
+ when File :: dict(),
Reason :: string().
reformat(File) ->
@@ -121,12 +164,24 @@ reformat(File) ->
%% ===========================================================================
-make(_, _, _, []) ->
+make(File, Opts, Dict) ->
+ ok(lists:foldl(fun(M,A) -> [make(File, Opts, Dict, M) | A] end,
+ [],
+ lists:append([[dict, forms] || lists:member(debug, Opts)])
+ ++ [erl, hrl])).
+%% The order in which results are generated (dict/forms/erl/hrl) is
+%% intentional, in order of more processing (except for hrl, which
+%% isn't needed by diameter itself), since an error raises an
+%% exception. The order of return results is the reverse.
+
+ok([ok,_|_]) ->
ok;
-make(File, Opts, Dict, [Mode | Rest]) ->
+ok([_,_|_] = L) ->
+ {ok, L}.
+
+make(File, Opts, Dict, Mode) ->
try
- ok = diameter_codegen:from_dict(File, Dict, Opts, Mode),
- make(File, Opts, Dict, Rest)
+ diameter_codegen:from_dict(File, Dict, Opts, Mode)
catch
error: Reason ->
erlang:error({Reason, Mode, erlang:get_stacktrace()})