diff options
Diffstat (limited to 'lib/ic/src/ic_file.erl')
-rw-r--r-- | lib/ic/src/ic_file.erl | 447 |
1 files changed, 447 insertions, 0 deletions
diff --git a/lib/ic/src/ic_file.erl b/lib/ic/src/ic_file.erl new file mode 100644 index 0000000000..6a99d6cfde --- /dev/null +++ b/lib/ic/src/ic_file.erl @@ -0,0 +1,447 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%% + +-module(ic_file). + +-include_lib("ic/src/ic.hrl"). + +%%----------------------------------------------------------------- +%% External exports +%%----------------------------------------------------------------- +-export([filename_push/4, filename_pop/2, open/2, close/1, remove_ext/1, join/2, + add_dot_erl/1, add_dot_hrl/1, add_dot_c/1, add_dot_h/1, add_dot_java/1, + add_dot_idl/1, javaInterfaceFilePush/3, javaInterfaceFilePop/1, + createDirectory/2, createJavaDirectory/2, open_java_file/3]). + +%%----------------------------------------------------------------- +%% Internal exports +%%----------------------------------------------------------------- +-export([]). + +%%----------------------------------------------------------------- +%% External functions +%%----------------------------------------------------------------- + +%%----------------------------------------------------------------- +%% Func: filename_push +%% +%% Pushes a file name, can also push ignore in which case means that +%% no files should ever be opened at this scope. Note that empty in +%% the file descriptor entries means that the file just isn't open +%% yet. +%%----------------------------------------------------------------- +filename_push(G, _N, ignore, _) -> + G#genobj{stubfile=[ignore | G#genobj.stubfile], + stubfiled=[ignore | G#genobj.stubfiled], + skelfile=[ignore | G#genobj.skelfile], + skelfiled=[ignore | G#genobj.skelfiled], + includefile=[ignore | G#genobj.includefile], + includefiled=[ignore | G#genobj.includefiled]}; + +filename_push(G, N, X, Lang) -> + Fullname = [ic_forms:get_id2(X) | N], + EName0 = ic_util:to_undersc(Fullname), + + DoGen = ic_genobj:do_gen(G), + + ImplName = find_impl_name(G, Fullname), + + {StubName, EName} = + case Lang of + erlang -> + {join(ic_options:get_opt(G, stubdir), add_dot_erl(EName0)), + EName0}; + erlang_template -> + {join(ic_options:get_opt(G, stubdir), add_dot_erl(ImplName)), + ImplName}; + c -> + {join(ic_options:get_opt(G, stubdir), add_dot_c(EName0)), + EName0}; + c_server -> + {join(ic_options:get_opt(G, stubdir), add_dot_c(EName0++"__s")), + EName0}; + erlang_template_no_gen -> + {undefined, EName0}; + erlang_no_stub -> + {undefined, EName0}; + c_no_stub -> + {undefined, EName0}; + c_server_no_stub -> + {undefined, EName0} + end, + Stub = if DoGen==true -> + case StubName of + undefined -> + ignore; + _ -> + ic_codegen:emit_stub_head(G, open(empty, StubName), EName, Lang) + end; + true -> ignore end, + + HrlName = case Lang of + erlang_template -> + ignore; + erlang_template_no_gen -> + ignore; + erlang -> + ?ifopt2(G, gen_hrl, + join(ic_options:get_opt(G, stubdir), add_dot_hrl(EName)), + ignore); + c -> + ?ifopt2(G, gen_hrl, + join(ic_options:get_opt(G, stubdir), add_dot_h(EName)), + ignore); + c_server -> + ?ifopt2(G, gen_hrl, + join(ic_options:get_opt(G, stubdir), + add_dot_h(EName++"__s")), + ignore); + erlang_no_stub -> + ?ifopt2(G, gen_hrl, + join(ic_options:get_opt(G, stubdir), add_dot_hrl(EName)), + ignore); + c_no_stub -> + ?ifopt2(G, gen_hrl, + join(ic_options:get_opt(G, stubdir), add_dot_h(EName)), + ignore); + c_server_no_stub -> + ?ifopt2(G, gen_hrl, + join(ic_options:get_opt(G, stubdir), + add_dot_h(EName++"__s")), + ignore) + end, + Hrl = if DoGen==true -> + case Lang of + erlang_template -> + ignore; + erlang_template_no_gen -> + ignore; + erlang_no_stub -> + ic_codegen:emit_hrl_head(G, open(empty, HrlName), + EName, erlang); + c_no_stub -> + ic_codegen:emit_hrl_head(G, open(empty, HrlName), + EName, c); + c_server_no_stub -> + ic_codegen:emit_hrl_head(G, open(empty, HrlName), + EName, c_server); + _ -> + ic_codegen:emit_hrl_head(G, open(empty, HrlName), + EName, Lang) + end; + true -> ignore end, + + G#genobj{impl=ImplName, + stubfile=[StubName | G#genobj.stubfile], + stubfiled=[Stub | G#genobj.stubfiled], + includefile=[HrlName | G#genobj.includefile], + includefiled=[Hrl | G#genobj.includefiled]}. + +%%----------------------------------------------------------------- +%% Func: join/2 +%% +%% Special version of filename join. +%%----------------------------------------------------------------- +join([], File) -> + File; +join(Path, File) -> + filename:join(Path, File). + + +%%----------------------------------------------------------------- +%% Func: filename_pop/2 +%%----------------------------------------------------------------- +filename_pop(G, Lang) -> +%% io:format("Popped file names: ~p~n", [hd(G#genobj.stubfile)]), +%% case is_skelfile_open(G) of +%% true -> emit_skel_footer(G); +%% false -> ok end, +%% close(hd(G#genobj.skelfiled)), + close(hd(G#genobj.stubfiled)), + ic_codegen:emit_hrl_foot(G, Lang), + close(hd(G#genobj.includefiled)), + G#genobj{stubfile=tl(G#genobj.stubfile), + stubfiled=tl(G#genobj.stubfiled), +%% skelfile=tl(G#genobj.skelfile), +%% skelfiled=tl(G#genobj.skelfiled), + includefile=tl(G#genobj.includefile), + includefiled=tl(G#genobj.includefiled)}. + + + +%%----------------------------------------------------------------- +%% Func: javaInterfaceFilePush/3 +%%----------------------------------------------------------------- +javaInterfaceFilePush(G, N, X) -> + Name = ic_forms:get_java_id(X), + {InterfaceFd, InterfaceFileName} = open_java_file(G, N, Name), + + StubClassName = "_" ++ Name ++ "Stub", + {StubFd, StubFileName} = open_java_file(G, N, StubClassName), + + SkelClassName = "_" ++ Name ++ "ImplBase", + {SkelFd, SkelFileName} = open_java_file(G, N, SkelClassName), + + HelperClassName = Name ++ "Helper", + {HelperFd, HelperFileName} = open_java_file(G, N, HelperClassName), + + HolderClassName = Name ++ "Holder", + {HolderFd, HolderFileName} = open_java_file(G, N, HolderClassName), + + G#genobj{ + interfacefile=[InterfaceFileName | G#genobj.interfacefile], + interfacefiled=[InterfaceFd | G#genobj.interfacefiled], + stubfile=[StubFileName | G#genobj.stubfile], + stubfiled=[StubFd | G#genobj.stubfiled], + skelfile=[SkelFileName | G#genobj.skelfile], + skelfiled=[SkelFd | G#genobj.skelfiled], + helperfile=[HelperFileName | G#genobj.helperfile], + helperfiled=[HelperFd | G#genobj.helperfiled], + holderfile=[HolderFileName | G#genobj.holderfile], + holderfiled=[HolderFd | G#genobj.holderfiled]}. + + + + + +%%----------------------------------------------------------------- +%% Func: javaInterfaceFilePop/1 +%%----------------------------------------------------------------- +javaInterfaceFilePop(G) -> + close(hd(G#genobj.interfacefiled)), + close(hd(G#genobj.stubfiled)), + close(hd(G#genobj.skelfiled)), + close(hd(G#genobj.helperfiled)), + close(hd(G#genobj.holderfiled)), + G#genobj{ + interfacefile=tl(G#genobj.interfacefile), + interfacefiled=tl(G#genobj.interfacefiled), + stubfile=tl(G#genobj.stubfile), + stubfiled=tl(G#genobj.stubfiled), + skelfile=tl(G#genobj.skelfile), + skelfiled=tl(G#genobj.skelfiled), + helperfile=tl(G#genobj.helperfile), + helperfiled=tl(G#genobj.helperfiled), + holderfile=tl(G#genobj.holderfile), + holderfiled=tl(G#genobj.holderfiled)}. + +%%----------------------------------------------------------------- +%% Func: createDirectory/2 +%%----------------------------------------------------------------- +createDirectory(_G, []) -> + ok; +createDirectory(G, Scope) -> + Path = ic_file:join(ic_options:get_opt(G, stubdir), ic_pragma:slashify(Scope)), + case file:make_dir(Path) of + ok -> + ok; + {error, eexist} -> + ok; + {error, Reason} -> + ic_error:fatal_error(G, {create_dir, Path, Reason}) + end. + + +%%----------------------------------------------------------------- +%% Func: createJavaDirectory/2 +%%----------------------------------------------------------------- +createJavaDirectory(_G, []) -> + ok; +createJavaDirectory(G, Scope) -> + JavaScope = ic_util:adjustScopeToJava(G,Scope), + Path = ic_file:join(ic_options:get_opt(G, stubdir), ic_pragma:slashify(JavaScope)), + case file:make_dir(Path) of + ok -> + ok; + {error, eexist} -> + ok; + {error, Reason} -> + ic_error:fatal_error(G, {create_dir, Path, Reason}) + end. + + + + +%%----------------------------------------------------------------- +%% Func: createJavaFileName/3 +%%----------------------------------------------------------------- +createJavaFileName(G, Scope, FName) -> + JavaScope = ic_util:adjustScopeToJava(G,Scope), + join(ic_options:get_opt(G, stubdir), + ic_pragma:slashify([FName++".java"|JavaScope])). + +%%----------------------------------------------------------------- +%% Func: close/2 (used to be file_close) +%%----------------------------------------------------------------- +close(empty) -> ok; +close(ignore) -> ok; +close(Fd) -> + file:close(Fd). + +%%----------------------------------------------------------------- +%% Func: remove_ext/1 +%%----------------------------------------------------------------- +remove_ext(File) -> + filename:rootname(filename:basename(File)). + +%%----------------------------------------------------------------- +%% Func: open/2 (used to be file_open) +%%----------------------------------------------------------------- +open(_, ignore) -> ignore; +open(empty, Name) -> + case file:open(Name, [raw, binary, write]) of + {ok, Fd} -> + Fd; + {error, Reason} -> + exit({error, Reason}) +%% ic_error:fatal_error(G, {open_file, Name, Reason}) + end. + +%%----------------------------------------------------------------- +%% Func: open_java_file/3 +%%----------------------------------------------------------------- +open_java_file(G, N, Name) -> + createJavaDirectory(G, N), + FName = createJavaFileName(G, N, Name), + case file:open(FName, [raw, binary, write]) of + {ok, Fd} -> + ic_codegen:emit_stub_head(G, Fd, Name, java), + emit_package(G, N, Fd), + {Fd, FName}; + {error, Reason} -> + ic_error:fatal_error(G, {open_file, FName, Reason}) + end. + +%%----------------------------------------------------------------- +%% Func: emit_package/3 +%%----------------------------------------------------------------- +emit_package(_G, [], _Fd) -> + ok; +emit_package(G, N, Fd) -> + ic_codegen:emit(Fd, "package ~s;\n", [ic_util:to_dot(G,N)]), + ic_codegen:nl(Fd). + +%%----------------------------------------------------------------- +%% Func: add_dot_erl/1 +%%----------------------------------------------------------------- +add_dot_erl(F) -> + File = ic_util:to_list(F), + F2 = lists:reverse(File), + case F2 of + [$l, $r, $e, $. | _Rest] -> + File; + _ -> + File ++ ".erl" + end. + +%%----------------------------------------------------------------- +%% Func: add_dot_hrl/1 +%%----------------------------------------------------------------- +add_dot_hrl(F) -> + File = ic_util:to_list(F), + F2 = lists:reverse(File), + case F2 of + [$l, $r, $h, $. | _Rest] -> + File; + _ -> + File ++ ".hrl" + end. + +%%----------------------------------------------------------------- +%% Func: add_dot_c/1 +%%----------------------------------------------------------------- +add_dot_c(F) -> + File = ic_util:to_list(F), + F2 = lists:reverse(File), + case F2 of + [$c, $. | _Rest] -> + File; + _ -> + File ++ ".c" + end. + +%%----------------------------------------------------------------- +%% Func: add_dot_h/1 +%%----------------------------------------------------------------- +add_dot_h(F) -> + File = ic_util:to_list(F), + F2 = lists:reverse(File), + case F2 of + [$h, $. | _Rest] -> + File; + _ -> + File ++ ".h" + end. + +%%----------------------------------------------------------------- +%% Func: add_dot_java/1 +%%----------------------------------------------------------------- +add_dot_java(F) -> + File = ic_util:to_list(F), + F2 = lists:reverse(File), + case F2 of + [$a, $v, $a, $j, $. | _Rest] -> + File; + _ -> + File ++ ".java" + end. + +%%----------------------------------------------------------------- +%% Func: add_dot_idl/1 +%%----------------------------------------------------------------- +add_dot_idl(F) -> + File = ic_util:to_list(F), + F2 = lists:reverse(File), + case F2 of + [$l, $d, $i, $. | _Rest] -> + File; + _ -> + File ++ ".idl" + end. + + +%%----------------------------------------------------------------- +%% Internal functions +%%----------------------------------------------------------------- + +%%-------------------------------------------------------------------- +%% +%% File handling stuff +%% +%% +%% Shall open a file for writing. Also sets up the generator with +%% usefull bits of information +%% +%%-------------------------------------------------------------------- +find_impl_name(G, Name) -> + N1 = ic_util:to_colon(Name), + N2 = ic_util:to_undersc(Name), + case {ic_options:get_opt(G, {impl, N1}), + ic_options:get_opt(G, {impl, N2})} of + {false, false} -> + case {ic_options:get_opt(G, {impl, "::"++N1}), + ic_options:get_opt(G, {impl, N2})} of + {false, false} -> N2 ++ "_impl"; + {X, _Y} when X /= false -> ic_util:to_list(X); + {_X, Y} when Y /= false -> ic_util:to_list(Y) + end; + {X, _Y} when X /= false -> ic_util:to_list(X); + {_X, Y} when Y /= false -> ic_util:to_list(Y) + end. |