1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1999-2016. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20%% 21 22-module(ic_file). 23 24-include_lib("ic/src/ic.hrl"). 25 26%%----------------------------------------------------------------- 27%% External exports 28%%----------------------------------------------------------------- 29-export([filename_push/4, filename_pop/2, open/2, close/1, remove_ext/1, join/2, 30 add_dot_erl/1, add_dot_hrl/1, add_dot_c/1, add_dot_h/1, add_dot_java/1, 31 add_dot_idl/1, javaInterfaceFilePush/3, javaInterfaceFilePop/1, 32 createDirectory/2, createJavaDirectory/2, open_java_file/3]). 33 34%%----------------------------------------------------------------- 35%% Internal exports 36%%----------------------------------------------------------------- 37-export([]). 38 39%%----------------------------------------------------------------- 40%% External functions 41%%----------------------------------------------------------------- 42 43%%----------------------------------------------------------------- 44%% Func: filename_push 45%% 46%% Pushes a file name, can also push ignore in which case means that 47%% no files should ever be opened at this scope. Note that empty in 48%% the file descriptor entries means that the file just isn't open 49%% yet. 50%%----------------------------------------------------------------- 51filename_push(G, _N, ignore, _) -> 52 G#genobj{stubfile=[ignore | G#genobj.stubfile], 53 stubfiled=[ignore | G#genobj.stubfiled], 54 skelfile=[ignore | G#genobj.skelfile], 55 skelfiled=[ignore | G#genobj.skelfiled], 56 includefile=[ignore | G#genobj.includefile], 57 includefiled=[ignore | G#genobj.includefiled]}; 58 59filename_push(G, N, X, Lang) -> 60 Fullname = [ic_forms:get_id2(X) | N], 61 EName0 = ic_util:to_undersc(Fullname), 62 63 DoGen = ic_genobj:do_gen(G), 64 65 ImplName = find_impl_name(G, Fullname), 66 67 {StubName, EName} = 68 case Lang of 69 erlang -> 70 {join(ic_options:get_opt(G, stubdir), add_dot_erl(EName0)), 71 EName0}; 72 erlang_template -> 73 {join(ic_options:get_opt(G, stubdir), add_dot_erl(ImplName)), 74 ImplName}; 75 c -> 76 {join(ic_options:get_opt(G, stubdir), add_dot_c(EName0)), 77 EName0}; 78 c_server -> 79 {join(ic_options:get_opt(G, stubdir), add_dot_c(EName0++"__s")), 80 EName0}; 81 erlang_template_no_gen -> 82 {undefined, EName0}; 83 erlang_no_stub -> 84 {undefined, EName0}; 85 c_no_stub -> 86 {undefined, EName0}; 87 c_server_no_stub -> 88 {undefined, EName0} 89 end, 90 Stub = if DoGen==true -> 91 case StubName of 92 undefined -> 93 ignore; 94 _ -> 95 ic_codegen:emit_stub_head(G, open(empty, StubName), EName, Lang) 96 end; 97 true -> ignore end, 98 99 HrlName = case Lang of 100 erlang_template -> 101 ignore; 102 erlang_template_no_gen -> 103 ignore; 104 erlang -> 105 ?ifopt2(G, gen_hrl, 106 join(ic_options:get_opt(G, stubdir), add_dot_hrl(EName)), 107 ignore); 108 c -> 109 ?ifopt2(G, gen_hrl, 110 join(ic_options:get_opt(G, stubdir), add_dot_h(EName)), 111 ignore); 112 c_server -> 113 ?ifopt2(G, gen_hrl, 114 join(ic_options:get_opt(G, stubdir), 115 add_dot_h(EName++"__s")), 116 ignore); 117 erlang_no_stub -> 118 ?ifopt2(G, gen_hrl, 119 join(ic_options:get_opt(G, stubdir), add_dot_hrl(EName)), 120 ignore); 121 c_no_stub -> 122 ?ifopt2(G, gen_hrl, 123 join(ic_options:get_opt(G, stubdir), add_dot_h(EName)), 124 ignore); 125 c_server_no_stub -> 126 ?ifopt2(G, gen_hrl, 127 join(ic_options:get_opt(G, stubdir), 128 add_dot_h(EName++"__s")), 129 ignore) 130 end, 131 Hrl = if DoGen==true -> 132 case Lang of 133 erlang_template -> 134 ignore; 135 erlang_template_no_gen -> 136 ignore; 137 erlang_no_stub -> 138 ic_codegen:emit_hrl_head(G, open(empty, HrlName), 139 EName, erlang); 140 c_no_stub -> 141 ic_codegen:emit_hrl_head(G, open(empty, HrlName), 142 EName, c); 143 c_server_no_stub -> 144 ic_codegen:emit_hrl_head(G, open(empty, HrlName), 145 EName, c_server); 146 _ -> 147 ic_codegen:emit_hrl_head(G, open(empty, HrlName), 148 EName, Lang) 149 end; 150 true -> ignore end, 151 152 G#genobj{impl=ImplName, 153 stubfile=[StubName | G#genobj.stubfile], 154 stubfiled=[Stub | G#genobj.stubfiled], 155 includefile=[HrlName | G#genobj.includefile], 156 includefiled=[Hrl | G#genobj.includefiled]}. 157 158%%----------------------------------------------------------------- 159%% Func: join/2 160%% 161%% Special version of filename join. 162%%----------------------------------------------------------------- 163join([], File) -> 164 File; 165join(Path, File) -> 166 filename:join(Path, File). 167 168 169%%----------------------------------------------------------------- 170%% Func: filename_pop/2 171%%----------------------------------------------------------------- 172filename_pop(G, Lang) -> 173%% io:format("Popped file names: ~p~n", [hd(G#genobj.stubfile)]), 174%% case is_skelfile_open(G) of 175%% true -> emit_skel_footer(G); 176%% false -> ok end, 177%% close(hd(G#genobj.skelfiled)), 178 close(hd(G#genobj.stubfiled)), 179 ic_codegen:emit_hrl_foot(G, Lang), 180 close(hd(G#genobj.includefiled)), 181 G#genobj{stubfile=tl(G#genobj.stubfile), 182 stubfiled=tl(G#genobj.stubfiled), 183%% skelfile=tl(G#genobj.skelfile), 184%% skelfiled=tl(G#genobj.skelfiled), 185 includefile=tl(G#genobj.includefile), 186 includefiled=tl(G#genobj.includefiled)}. 187 188 189 190%%----------------------------------------------------------------- 191%% Func: javaInterfaceFilePush/3 192%%----------------------------------------------------------------- 193javaInterfaceFilePush(G, N, X) -> 194 Name = ic_forms:get_java_id(X), 195 {InterfaceFd, InterfaceFileName} = open_java_file(G, N, Name), 196 197 StubClassName = "_" ++ Name ++ "Stub", 198 {StubFd, StubFileName} = open_java_file(G, N, StubClassName), 199 200 SkelClassName = "_" ++ Name ++ "ImplBase", 201 {SkelFd, SkelFileName} = open_java_file(G, N, SkelClassName), 202 203 HelperClassName = Name ++ "Helper", 204 {HelperFd, HelperFileName} = open_java_file(G, N, HelperClassName), 205 206 HolderClassName = Name ++ "Holder", 207 {HolderFd, HolderFileName} = open_java_file(G, N, HolderClassName), 208 209 G#genobj{ 210 interfacefile=[InterfaceFileName | G#genobj.interfacefile], 211 interfacefiled=[InterfaceFd | G#genobj.interfacefiled], 212 stubfile=[StubFileName | G#genobj.stubfile], 213 stubfiled=[StubFd | G#genobj.stubfiled], 214 skelfile=[SkelFileName | G#genobj.skelfile], 215 skelfiled=[SkelFd | G#genobj.skelfiled], 216 helperfile=[HelperFileName | G#genobj.helperfile], 217 helperfiled=[HelperFd | G#genobj.helperfiled], 218 holderfile=[HolderFileName | G#genobj.holderfile], 219 holderfiled=[HolderFd | G#genobj.holderfiled]}. 220 221 222 223 224 225%%----------------------------------------------------------------- 226%% Func: javaInterfaceFilePop/1 227%%----------------------------------------------------------------- 228javaInterfaceFilePop(G) -> 229 close(hd(G#genobj.interfacefiled)), 230 close(hd(G#genobj.stubfiled)), 231 close(hd(G#genobj.skelfiled)), 232 close(hd(G#genobj.helperfiled)), 233 close(hd(G#genobj.holderfiled)), 234 G#genobj{ 235 interfacefile=tl(G#genobj.interfacefile), 236 interfacefiled=tl(G#genobj.interfacefiled), 237 stubfile=tl(G#genobj.stubfile), 238 stubfiled=tl(G#genobj.stubfiled), 239 skelfile=tl(G#genobj.skelfile), 240 skelfiled=tl(G#genobj.skelfiled), 241 helperfile=tl(G#genobj.helperfile), 242 helperfiled=tl(G#genobj.helperfiled), 243 holderfile=tl(G#genobj.holderfile), 244 holderfiled=tl(G#genobj.holderfiled)}. 245 246%%----------------------------------------------------------------- 247%% Func: createDirectory/2 248%%----------------------------------------------------------------- 249createDirectory(_G, []) -> 250 ok; 251createDirectory(G, Scope) -> 252 Path = ic_file:join(ic_options:get_opt(G, stubdir), ic_pragma:slashify(Scope)), 253 case file:make_dir(Path) of 254 ok -> 255 ok; 256 {error, eexist} -> 257 ok; 258 {error, Reason} -> 259 ic_error:fatal_error(G, {create_dir, Path, Reason}) 260 end. 261 262 263%%----------------------------------------------------------------- 264%% Func: createJavaDirectory/2 265%%----------------------------------------------------------------- 266createJavaDirectory(_G, []) -> 267 ok; 268createJavaDirectory(G, Scope) -> 269 JavaScope = ic_util:adjustScopeToJava(G,Scope), 270 Path = ic_file:join(ic_options:get_opt(G, stubdir), ic_pragma:slashify(JavaScope)), 271 case file:make_dir(Path) of 272 ok -> 273 ok; 274 {error, eexist} -> 275 ok; 276 {error, Reason} -> 277 ic_error:fatal_error(G, {create_dir, Path, Reason}) 278 end. 279 280 281 282 283%%----------------------------------------------------------------- 284%% Func: createJavaFileName/3 285%%----------------------------------------------------------------- 286createJavaFileName(G, Scope, FName) -> 287 JavaScope = ic_util:adjustScopeToJava(G,Scope), 288 join(ic_options:get_opt(G, stubdir), 289 ic_pragma:slashify([FName++".java"|JavaScope])). 290 291%%----------------------------------------------------------------- 292%% Func: close/2 (used to be file_close) 293%%----------------------------------------------------------------- 294close(empty) -> ok; 295close(ignore) -> ok; 296close(Fd) -> 297 file:close(Fd). 298 299%%----------------------------------------------------------------- 300%% Func: remove_ext/1 301%%----------------------------------------------------------------- 302remove_ext(File) -> 303 filename:rootname(filename:basename(File)). 304 305%%----------------------------------------------------------------- 306%% Func: open/2 (used to be file_open) 307%%----------------------------------------------------------------- 308open(_, ignore) -> ignore; 309open(empty, Name) -> 310 case file:open(Name, [raw, binary, write]) of 311 {ok, Fd} -> 312 Fd; 313 {error, Reason} -> 314 exit({error, Reason}) 315%% ic_error:fatal_error(G, {open_file, Name, Reason}) 316 end. 317 318%%----------------------------------------------------------------- 319%% Func: open_java_file/3 320%%----------------------------------------------------------------- 321open_java_file(G, N, Name) -> 322 createJavaDirectory(G, N), 323 FName = createJavaFileName(G, N, Name), 324 case file:open(FName, [raw, binary, write]) of 325 {ok, Fd} -> 326 ic_codegen:emit_stub_head(G, Fd, Name, java), 327 emit_package(G, N, Fd), 328 {Fd, FName}; 329 {error, Reason} -> 330 ic_error:fatal_error(G, {open_file, FName, Reason}) 331 end. 332 333%%----------------------------------------------------------------- 334%% Func: emit_package/3 335%%----------------------------------------------------------------- 336emit_package(_G, [], _Fd) -> 337 ok; 338emit_package(G, N, Fd) -> 339 ic_codegen:emit(Fd, "package ~s;\n", [ic_util:to_dot(G,N)]), 340 ic_codegen:nl(Fd). 341 342%%----------------------------------------------------------------- 343%% Func: add_dot_erl/1 344%%----------------------------------------------------------------- 345add_dot_erl(F) -> 346 File = ic_util:to_list(F), 347 F2 = lists:reverse(File), 348 case F2 of 349 [$l, $r, $e, $. | _Rest] -> 350 File; 351 _ -> 352 File ++ ".erl" 353 end. 354 355%%----------------------------------------------------------------- 356%% Func: add_dot_hrl/1 357%%----------------------------------------------------------------- 358add_dot_hrl(F) -> 359 File = ic_util:to_list(F), 360 F2 = lists:reverse(File), 361 case F2 of 362 [$l, $r, $h, $. | _Rest] -> 363 File; 364 _ -> 365 File ++ ".hrl" 366 end. 367 368%%----------------------------------------------------------------- 369%% Func: add_dot_c/1 370%%----------------------------------------------------------------- 371add_dot_c(F) -> 372 File = ic_util:to_list(F), 373 F2 = lists:reverse(File), 374 case F2 of 375 [$c, $. | _Rest] -> 376 File; 377 _ -> 378 File ++ ".c" 379 end. 380 381%%----------------------------------------------------------------- 382%% Func: add_dot_h/1 383%%----------------------------------------------------------------- 384add_dot_h(F) -> 385 File = ic_util:to_list(F), 386 F2 = lists:reverse(File), 387 case F2 of 388 [$h, $. | _Rest] -> 389 File; 390 _ -> 391 File ++ ".h" 392 end. 393 394%%----------------------------------------------------------------- 395%% Func: add_dot_java/1 396%%----------------------------------------------------------------- 397add_dot_java(F) -> 398 File = ic_util:to_list(F), 399 F2 = lists:reverse(File), 400 case F2 of 401 [$a, $v, $a, $j, $. | _Rest] -> 402 File; 403 _ -> 404 File ++ ".java" 405 end. 406 407%%----------------------------------------------------------------- 408%% Func: add_dot_idl/1 409%%----------------------------------------------------------------- 410add_dot_idl(F) -> 411 File = ic_util:to_list(F), 412 F2 = lists:reverse(File), 413 case F2 of 414 [$l, $d, $i, $. | _Rest] -> 415 File; 416 _ -> 417 File ++ ".idl" 418 end. 419 420 421%%----------------------------------------------------------------- 422%% Internal functions 423%%----------------------------------------------------------------- 424 425%%-------------------------------------------------------------------- 426%% 427%% File handling stuff 428%% 429%% 430%% Shall open a file for writing. Also sets up the generator with 431%% usefull bits of information 432%% 433%%-------------------------------------------------------------------- 434find_impl_name(G, Name) -> 435 N1 = ic_util:to_colon(Name), 436 N2 = ic_util:to_undersc(Name), 437 case {ic_options:get_opt(G, {impl, N1}), 438 ic_options:get_opt(G, {impl, N2})} of 439 {false, false} -> 440 case {ic_options:get_opt(G, {impl, "::"++N1}), 441 ic_options:get_opt(G, {impl, N2})} of 442 {false, false} -> N2 ++ "_impl"; 443 {X, _Y} when X /= false -> ic_util:to_list(X); 444 {_X, Y} when Y /= false -> ic_util:to_list(Y) 445 end; 446 {X, _Y} when X /= false -> ic_util:to_list(X); 447 {_X, Y} when Y /= false -> ic_util:to_list(Y) 448 end. 449