%% %% %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.