1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2004-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-module(ic_erl_template). 22 23 24-export([do_gen/3, emit_header/3]). 25 26-import(ic_codegen, [emit/2, emit/3, nl/1]). 27 28-include("icforms.hrl"). 29-include("ic.hrl"). 30 31-include_lib("stdlib/include/erl_compile.hrl"). 32 33-define(TAB, " "). 34-define(TAB2, "% "). 35 36-define(TEMPLATE_1_A, 37 "%%----------------------------------------------------------------------\n" 38 "%% <LICENSE>\n" 39 "%% \n" 40 "%% $Id$\n" 41 "%%\n" 42 "%%----------------------------------------------------------------------\n" 43 "%% Module : ~s.erl\n" 44 "%% \n" 45 "%% Source : ~s\n" 46 "%% \n" 47 "%% Description : \n" 48 "%% \n" 49 "%% Creation date: ~s\n" 50 "%%\n" 51 "%%----------------------------------------------------------------------\n" 52 "-module(~p).\n\n"). 53 54-define(TEMPLATE_1_B, 55 "%%----------------------------------------------------------------------\n" 56 "%% Internal Exports\n" 57 "%%----------------------------------------------------------------------\n" 58 "-export([init/1,\n" 59 " terminate/2,\n" 60 " code_change/3,\n" 61 " handle_info/2]).\n\n" 62 "%%----------------------------------------------------------------------\n" 63 "%% Include Files\n" 64 "%%----------------------------------------------------------------------\n" 65 "\n\n" 66 "%%----------------------------------------------------------------------\n" 67 "%% Macros\n" 68 "%%----------------------------------------------------------------------\n" 69 "\n\n" 70 "%%----------------------------------------------------------------------\n" 71 "%% Records\n" 72 "%%----------------------------------------------------------------------\n" 73 "-record(state, {}).\n\n" 74 "%%======================================================================\n" 75 "%% API Functions\n" 76 "%%======================================================================\n"). 77 78-define(TEMPLATE_1_C, 79 "%%======================================================================\n" 80 "%% Internal Functions\n" 81 "%%======================================================================\n" 82 "%%----------------------------------------------------------------------\n" 83 "%% Function : init/1\n" 84 "%% Arguments : Env = term()\n" 85 "%% Returns : {ok, State} |\n" 86 "%% {ok, State, Timeout} |\n" 87 "%% ignore |\n" 88 "%% {stop, Reason}\n" 89 "%% Raises : -\n" 90 "%% Description: Initiates the server\n" 91 "%%----------------------------------------------------------------------\n" 92 "init(_Env) ->\n" 93 "\t{ok, #state{}}.\n\n\n" 94 "%%----------------------------------------------------------------------\n" 95 "%% Function : terminate/2\n" 96 "%% Arguments : Reason = normal | shutdown | term()\n" 97 "%% State = term()\n" 98 "%% Returns : ok\n" 99 "%% Raises : -\n" 100 "%% Description: Invoked when the object is terminating.\n" 101 "%%----------------------------------------------------------------------\n" 102 "terminate(_Reason, _State) ->\n" 103 "\tok.\n\n\n" 104 "%%----------------------------------------------------------------------\n" 105 "%% Function : code_change/3\n" 106 "%% Arguments : OldVsn = undefined | term()\n" 107 "%% State = NewState = term()\n" 108 "%% Extra = term()\n" 109 "%% Returns : {ok, NewState}\n" 110 "%% Raises : -\n" 111 "%% Description: Invoked when the object should update its internal state\n" 112 "%% due to code replacement.\n" 113 "%%----------------------------------------------------------------------\n" 114 "code_change(_OldVsn, State, _Extra) ->\n" 115 "\t{ok, State}.\n\n\n" 116 "%%----------------------------------------------------------------------\n" 117 "%% Function : handle_info/2\n" 118 "%% Arguments : Info = normal | shutdown | term()\n" 119 "%% State = NewState = term()\n" 120 "%% Returns : {noreply, NewState} |\n" 121 "%% {noreply, NewState, Timeout} |\n" 122 "%% {stop, Reason, NewState}\n" 123 "%% Raises : -\n" 124 "%% Description: Invoked when, for example, the server traps exits.\n" 125 "%%----------------------------------------------------------------------\n" 126 "handle_info(_Info, State) ->\n" 127 "\t{noreply, State}.\n\n\n"). 128 129-define(TEMPLATE_2_A, 130 "%%% #0. BASIC INFORMATION\n" 131 "%%% ----------------------------------------------------------------------\n" 132 "%%% %CCaseFile : ~s.erl %\n" 133 "%%% Author : \n" 134 "%%% Description : \n" 135 "%%%\n" 136 "%%% Modules used: \n" 137 "%%%\n" 138 "%%%\n" 139 "%%% ----------------------------------------------------------------------\n" 140 "-module(~p).\n" 141 "-author('unknown').\n" 142 "-id('').\n" 143 "-vsn('').\n" 144 "-date('~s').\n\n" 145 "%%% ----------------------------------------------------------------------\n" 146 "%%% Template Id: <ID>\n" 147 "%%%\n" 148 "%%% #Copyright (C) 2004\n" 149 "%%% by <COMPANY>\n" 150 "%%% <ADDRESS>\n" 151 "%%% <OTHER INFORMATION>\n" 152 "%%% \n" 153 "%%% <LICENSE>\n" 154 "%%% \n" 155 "%%% \n" 156 "%%% ----------------------------------------------------------------------\n" 157 "%%% #1. REVISION LOG\n" 158 "%%% ----------------------------------------------------------------------\n" 159 "%%% Rev Date Name What\n" 160 "%%% ----- ------- -------- --------------------------\n" 161 "%%% \n" 162 "%%% ----------------------------------------------------------------------\n" 163 "%%%\n" 164 "%%% \n" 165 "%%% #2. EXPORT LISTS\n" 166 "%%% ----------------------------------------------------------------------\n" 167 "%%% #2.1 EXPORTED INTERFACE FUNCTIONS\n" 168 "%%% ----------------------------------------------------------------------\n"). 169 170-define(TEMPLATE_2_B, 171 "%%% ----------------------------------------------------------------------\n" 172 "%%% #2.2 EXPORTED INTERNAL FUNCTIONS\n" 173 "%%% ----------------------------------------------------------------------\n" 174 "-export([init/1,\n" 175 " terminate/2,\n" 176 " code_change/3,\n" 177 " handle_info/2]).\n\n" 178 "%%% ----------------------------------------------------------------------\n" 179 "%%% #2.3 INCLUDE FILES\n" 180 "%%% ----------------------------------------------------------------------\n" 181 "\n\n" 182 "%%% ----------------------------------------------------------------------\n" 183 "%%% #2.4 MACROS\n" 184 "%%% ----------------------------------------------------------------------\n" 185 "\n\n" 186 "%%% ----------------------------------------------------------------------\n" 187 "%%% #2.5 RECORDS\n" 188 "%%% ----------------------------------------------------------------------\n" 189 "-record(state, {}).\n\n" 190 "%%% ----------------------------------------------------------------------\n" 191 "%%% #3. CODE\n" 192 "%%% #---------------------------------------------------------------------\n" 193 "%%% #3.1 CODE FOR EXPORTED INTERFACE FUNCTIONS\n" 194 "%%% #---------------------------------------------------------------------\n"). 195 196-define(TEMPLATE_2_C, 197 "%%% ----------------------------------------------------------------------\n" 198 "%%% #3.3 CODE FOR INTERNAL FUNCTIONS\n" 199 "%%% ----------------------------------------------------------------------\n" 200 "%%% ----------------------------------------------------------------------\n" 201 "%%% # init/1\n" 202 "%%% Input : Env = term()\n" 203 "%%% Output : {ok, State} |\n" 204 "%%% {ok, State, Timeout} |\n" 205 "%%% ignore |\n" 206 "%%% {stop, Reason}\n" 207 "%%% Exceptions : -\n" 208 "%%% Description: Initiates the server\n" 209 "%%% ----------------------------------------------------------------------\n" 210 "init(_Env) ->\n" 211 "\t{ok, #state{}}.\n\n\n" 212 "%%% ----------------------------------------------------------------------\n" 213 "%%% # terminate/2\n" 214 "%%% Input : Reason = normal | shutdown | term()\n" 215 "%%% State = term()\n" 216 "%%% Output : ok\n" 217 "%%% Exceptions : -\n" 218 "%%% Description: Invoked when the object is terminating.\n" 219 "%%% ----------------------------------------------------------------------\n" 220 "terminate(_Reason, _State) ->\n" 221 "\tok.\n\n\n" 222 "%%% ----------------------------------------------------------------------\n" 223 "%%% # code_change/3\n" 224 "%%% Input : OldVsn = undefined | term()\n" 225 "%%% State = NewState = term()\n" 226 "%%% Extra = term()\n" 227 "%%% Output : {ok, NewState}\n" 228 "%%% Exceptions : -\n" 229 "%%% Description: Invoked when the object should update its internal state\n" 230 "%%% due to code replacement.\n" 231 "%%% ----------------------------------------------------------------------\n" 232 "code_change(_OldVsn, State, _Extra) ->\n" 233 "\t{ok, State}.\n\n\n" 234 "%%% ----------------------------------------------------------------------\n" 235 "%%% # handle_info/2\n" 236 "%%% Input : Info = normal | shutdown | term()\n" 237 "%%% State = NewState = term()\n" 238 "%%% Output : {noreply, NewState} |\n" 239 "%%% {noreply, NewState, Timeout} |\n" 240 "%%% {stop, Reason, NewState}\n" 241 "%%% Exceptions : -\n" 242 "%%% Description: Invoked when, for example, the server traps exits.\n" 243 "%%% ----------------------------------------------------------------------\n" 244 "handle_info(_Info, State) ->\n" 245 "\t{noreply, State}.\n\n\n" 246 "%%% ----------------------------------------------------------------------\n" 247 "%%% #4 CODE FOR TEMPORARY CORRECTIONS\n" 248 "%%% ----------------------------------------------------------------------\n\n"). 249 250 251%%------------------------------------------------------------ 252%% 253%% Generate the client side Erlang stubs. 254%% 255%% Each module is generated to a separate file. 256%% 257%% Export declarations for all interface functions must be 258%% generated. Each function then needs to generate a function head and 259%% a body. IDL parameters must be converted into Erlang parameters 260%% (variables, capitalised) and a type signature list must be 261%% generated (for later encode/decode). 262%% 263%%------------------------------------------------------------ 264do_gen(G, _File, Form) -> 265 gen_head(G, [], Form), 266 gen(G, [], Form). 267 268 269gen(G, N, [X|Xs]) when is_record(X, preproc) -> 270 NewG = ic:handle_preproc(G, N, X#preproc.cat, X), 271 gen(NewG, N, Xs); 272gen(G, N, [X|Xs]) when is_record(X, module) -> 273 G2 = ic_file:filename_push(G, N, X, erlang_template_no_gen), 274 N2 = [ic_forms:get_id2(X) | N], 275 gen_head(G2, N2, X), 276 gen(G2, N2, ic_forms:get_body(X)), 277 G3 = ic_file:filename_pop(G2, erlang_template_no_gen), 278 gen(G3, N, Xs); 279gen(G, N, [X|Xs]) when is_record(X, interface) -> 280 G2 = ic_file:filename_push(G, N, X, erlang_template), 281 N2 = [ic_forms:get_id2(X) | N], 282 gen_head(G2, N2, X), 283 gen(G2, N2, ic_forms:get_body(X)), 284 lists:foreach(fun({_Name, Body}) -> gen(G2, N2, Body) end, 285 X#interface.inherit_body), 286 Fd = ic_genobj:stubfiled(G2), 287 case get_template_version(G2) of 288 ?IC_FLAG_TEMPLATE_2 -> 289 emit(Fd, ?TEMPLATE_2_C, []); 290 _ -> 291 emit(Fd, ?TEMPLATE_1_C, []) 292 end, 293 G3 = ic_file:filename_pop(G2, erlang_template), 294 gen(G3, N, Xs); 295gen(G, N, [X|Xs]) when is_record(X, op) -> 296 {Name, InArgNames, OutArgNames, Reply} = extract_info(X), 297 emit_function(G, N, X, ic_genobj:is_stubfile_open(G), 298 ic_forms:is_oneway(X), Name, InArgNames, OutArgNames, Reply), 299 gen(G, N, Xs); 300gen(G, N, [X|Xs]) when is_record(X, attr) -> 301 emit_attr(G, N, X, ic_genobj:is_stubfile_open(G), fun emit_function/9), 302 gen(G, N, Xs); 303gen(G, N, [_X|Xs]) -> 304 gen(G, N, Xs); 305gen(_G, _N, []) -> 306 ok. 307 308%% Module Header 309emit_header(G, Fd, Name) -> 310 Date = get_date(), 311 case get_template_version(G) of 312 ?IC_FLAG_TEMPLATE_2 -> 313 emit(Fd, ?TEMPLATE_2_A, [Name, list_to_atom(Name), Date]); 314 _ -> 315 IDLFile = ic_genobj:idlfile(G), 316 emit(Fd, ?TEMPLATE_1_A, [Name, IDLFile, Date, list_to_atom(Name)]) 317 end. 318 319 320emit_attr(G, N, X, Open, F) -> 321 XX = #id_of{type=X}, 322 lists:foreach(fun(Id) -> 323 X2 = XX#id_of{id=Id}, 324 IsOneWay = ic_forms:is_oneway(X2), 325 {Get, Set} = mk_attr_func_names(N, ic_forms:get_id(Id)), 326 F(G, N, X2, Open, IsOneWay, Get, [], [], 327 [{ic_util:mk_var(ic_forms:get_id(Id)), 328 ic_forms:get_tk(X)}]), 329 case X#attr.readonly of 330 {readonly, _} -> 331 ok; 332 _ -> 333 F(G, N, X2, Open, IsOneWay, Set, 334 [{ic_util:mk_var(ic_forms:get_id(Id)), 335 ic_forms:get_tk(X)}], [], ["ok"]) 336 end 337 end, ic_forms:get_idlist(X)). 338 339 340%% The automaticly generated get and set operation names for an 341%% attribute. 342mk_attr_func_names(_Scope, Name) -> 343 {"_get_" ++ Name, "_set_" ++ Name}. 344 345 346extract_info(X) when is_record(X, op) -> 347 Name = ic_forms:get_id2(X), 348 InArgs = ic:filter_params([in,inout], X#op.params), 349 OutArgs = ic:filter_params([out,inout], X#op.params), 350 Reply = case ic_forms:get_tk(X) of 351 tk_void -> 352 ["ok"]; 353 Type -> 354 [{"OE_Reply", Type}] 355 end, 356 InArgsTypeList = 357 [{ic_util:mk_var(ic_forms:get_id(InArg#param.id)), 358 ic_forms:get_tk(InArg)} || InArg <- InArgs ], 359 OutArgsTypeList = 360 [{ic_util:mk_var(ic_forms:get_id(OutArg#param.id)), 361 ic_forms:get_tk(OutArg)} || OutArg <- OutArgs ], 362 {Name, InArgsTypeList, OutArgsTypeList, Reply}. 363 364get_template_version(G) -> 365 case ic_options:get_opt(G, flags) of 366 Flags when is_integer(Flags) -> 367 case ?IC_FLAG_TEST(Flags, ?IC_FLAG_TEMPLATE_2) of 368 true -> 369 ?IC_FLAG_TEMPLATE_2; 370 false -> 371 ?IC_FLAG_TEMPLATE_1 372 end; 373 _ -> 374 ?IC_FLAG_TEMPLATE_1 375 end. 376 377 378get_date() -> 379 {{Y,M,D}, _} = calendar:now_to_datetime(erlang:timestamp()), 380 if 381 M < 10, D < 10 -> 382 lists:concat([Y, "-0", M, "-0",D]); 383 M < 10 -> 384 lists:concat([Y, "-0", M, "-", D]); 385 D < 10 -> 386 lists:concat([Y, "-", M, "-0", D]); 387 true -> 388 lists:concat([Y, "-", M, "-", D]) 389 end. 390 391 392%%------------------------------------------------------------ 393%% 394%% Export stuff 395%% 396%% Gathering of all names that should be exported from a stub 397%% file. 398%% 399 400 401gen_head_special(G, N, X) when is_record(X, interface) -> 402 Fd = ic_genobj:stubfiled(G), 403 lists:foreach(fun({_Name, Body}) -> 404 ic_codegen:export(Fd, exp_top(G, N, Body, [])) 405 end, X#interface.inherit_body), 406 nl(Fd), 407 ok; 408gen_head_special(_G, _N, _X) -> 409 ok. 410 411 412%% Generate all export declarations 413gen_head(G, N, X) -> 414 case ic_genobj:is_stubfile_open(G) of 415 true -> 416 Fd = ic_genobj:stubfiled(G), 417 ic_codegen:export(Fd, exp_top(G, N, X, [])), 418 gen_head_special(G, N, X), 419 case get_template_version(G) of 420 ?IC_FLAG_TEMPLATE_2 -> 421 emit(Fd, ?TEMPLATE_2_B, []); 422 _ -> 423 emit(Fd, ?TEMPLATE_1_B, []) 424 end; 425 false -> 426 ok 427 end. 428 429exp_top(_G, _N, X, Acc) when element(1, X) == preproc -> 430 Acc; 431exp_top(G, N, L, Acc) when is_list(L) -> 432 exp_list(G, N, L, Acc); 433exp_top(G, N, M, Acc) when is_record(M, module) -> 434 exp_list(G, N, ic_forms:get_body(M), Acc); 435exp_top(G, N, I, Acc) when is_record(I, interface) -> 436 exp_list(G, N, ic_forms:get_body(I), Acc); 437exp_top(G, N, X, Acc) -> 438 exp3(G, N, X, Acc). 439 440exp3(G, N, Op, Acc) when is_record(Op, op) -> 441 FuncName = ic_forms:get_id(Op#op.id), 442 Arity = length(ic:filter_params([in, inout], Op#op.params)) + 1 + 443 count_extras(G, N, Op), 444 [{FuncName, Arity} | Acc]; 445exp3(G, N, A, Acc) when is_record(A, attr) -> 446 Extra = count_extras(G, N, A), 447 lists:foldr(fun(Id, Acc2) -> 448 {Get, Set} = mk_attr_func_names([], ic_forms:get_id(Id)), 449 case A#attr.readonly of 450 {readonly, _} -> 451 [{Get, 1 + Extra} | Acc2]; 452 _ -> 453 [{Get, 1 + Extra}, {Set, 2 + Extra} | Acc2] 454 end 455 end, Acc, ic_forms:get_idlist(A)); 456exp3(_G, _N, _X, Acc) -> 457 Acc. 458 459exp_list(G, N, L, OrigAcc) -> 460 lists:foldr(fun(X, Acc) -> 461 exp3(G, N, X, Acc) 462 end, OrigAcc, L). 463 464count_extras(G, N, Op) -> 465 case {use_this(G, N, Op), use_from(G, N, Op)} of 466 {[], []} -> 467 0; 468 {[], _} -> 469 1; 470 {_, []} -> 471 1; 472 _ -> 473 2 474 end. 475 476%%------------------------------------------------------------ 477%% 478%% Emit stuff 479%% 480%% Low level generation primitives 481%% 482 483emit_function(_G, _N, _X, false, _, _, _, _, _) -> 484 ok; 485emit_function(G, N, X, true, false, Name, InArgs, OutArgs, Reply) -> 486 Fd = ic_genobj:stubfiled(G), 487 This = use_this(G, N, Name), 488 From = use_from(G, N, Name), 489 State = ["State"], 490 Vers = get_template_version(G), 491 case OutArgs of 492 [] -> 493 ReplyString = create_string(Reply), 494 emit_function_header(G, Fd, X, N, Name, create_extra(This, From, Vers), 495 InArgs, length(InArgs), OutArgs, Reply, 496 ReplyString, Vers), 497 emit(Fd, "~p(~s) ->\n\t{reply, ~s, State}.\n\n", 498 [ic_util:to_atom(Name), create_string(This ++ From ++ State ++ InArgs), 499 ReplyString]); 500 _ -> 501 ReplyString = "{" ++ create_string(Reply ++ OutArgs) ++ "}", 502 emit_function_header(G, Fd, X, N, Name, create_extra(This, From, Vers), 503 InArgs, length(InArgs), OutArgs, Reply, 504 ReplyString, Vers), 505 emit(Fd, "~p(~s) ->\n\t{reply, ~s, State}.\n\n", 506 [ic_util:to_atom(Name), create_string(This ++ From ++ State ++ InArgs), 507 ReplyString]) 508 end; 509emit_function(G, N, X, true, true, Name, InArgs, _OutArgs, _Reply) -> 510 Fd = ic_genobj:stubfiled(G), 511 This = use_this(G, N, Name), 512 State = ["State"], 513 Vers = get_template_version(G), 514 emit_function_header(G, Fd, X, N, Name, create_extra(This, [], Vers), 515 InArgs, length(InArgs), "", "", "", Vers), 516 emit(Fd, "~p(~s) ->\n\t{noreply, State}.\n\n", 517 [ic_util:to_atom(Name), create_string(This ++ State ++ InArgs)]). 518 519create_string([]) -> 520 ""; 521create_string([{Name, _Type}|T]) -> 522 Name ++ create_string2(T); 523create_string([Name|T]) -> 524 Name ++ create_string2(T). 525 526create_string2([{Name, _Type}|T]) -> 527 ", " ++ Name ++ create_string2(T); 528create_string2([Name|T]) -> 529 ", " ++ Name ++ create_string2(T); 530create_string2([]) -> 531 "". 532 533create_extra([], [], _Vers) -> 534 {"State - term()", 1}; 535create_extra([], _From, ?IC_FLAG_TEMPLATE_2) -> 536 {"OE_From - term()\n%%% " ++ ?TAB ++ "State - term()", 2}; 537create_extra([], _From, _Vers) -> 538 {"OE_From - term()\n%% " ++ ?TAB ++ "State - term()", 2}; 539create_extra(_This, [], ?IC_FLAG_TEMPLATE_2) -> 540 {"OE_This - #objref{} (i.e., self())\n%%% " ++ ?TAB ++ "State - term()", 2}; 541create_extra(_This, [], _Vers) -> 542 {"OE_This - #objref{} (i.e., self())\n%% " ++ ?TAB ++ "State - term()", 2}; 543create_extra(_This, _From, ?IC_FLAG_TEMPLATE_2) -> 544 {"OE_This - #objref{} (i.e., self())\n%%% " ++ ?TAB ++ 545 "OE_From - term()\n%%% " ++ ?TAB ++ "State - term()", 3}; 546create_extra(_This, _From, _Vers) -> 547 {"OE_This - #objref{} (i.e., self())\n%% " ++ ?TAB ++ 548 "OE_From - term()\n%% " ++ ?TAB ++ "State - term()", 3}. 549 550use_this(G, N, OpName) -> 551 FullOp = ic_util:to_colon([OpName|N]), 552 FullIntf = ic_util:to_colon(N), 553 case {ic_options:get_opt(G, {this, FullIntf}), 554 ic_options:get_opt(G, {this, FullOp}), 555 ic_options:get_opt(G, {this, true})} of 556 {_, force_false, _} -> 557 []; 558 {force_false, false, _} -> 559 []; 560 {false, false, false} -> 561 []; 562 _ -> 563 ["OE_This"] 564 end. 565 566use_from(G, N, OpName) -> 567 FullOp = ic_util:to_colon([OpName|N]), 568 FullIntf = ic_util:to_colon(N), 569 case {ic_options:get_opt(G, {from, FullIntf}), 570 ic_options:get_opt(G, {from, FullOp}), 571 ic_options:get_opt(G, {from, true})} of 572 {_, force_false, _} -> 573 []; 574 {force_false, false, _} -> 575 []; 576 {false, false, false} -> 577 []; 578 _ -> 579 ["OE_From"] 580 end. 581 582 583emit_function_header(G, Fd, X, N, Name, {Extra, ExtraNo}, InP, Arity, OutP, 584 Reply, ReplyString, ?IC_FLAG_TEMPLATE_2) -> 585 emit(Fd, 586 "%%% ----------------------------------------------------------------------\n" 587 "%%% # ~p/~p\n" 588 "%%% Input : ~s\n", 589 [ic_util:to_atom(Name), (ExtraNo+Arity), Extra]), 590 ic_code:type_expand_all(G, N, X, Fd, ?TAB2, InP), 591 case Reply of 592 ["ok"] -> 593 emit(Fd, "%%% Output : ReturnValue = ~s\n", [ReplyString]); 594 _ -> 595 emit(Fd, "%%% Output : ReturnValue = ~s\n", [ReplyString]), 596 ic_code:type_expand_all(G, N, X, Fd, "% ", Reply) 597 end, 598 ic_code:type_expand_all(G, N, X, Fd, ?TAB2, OutP), 599 emit(Fd, 600 "%%% Exceptions : ~s\n" 601 "%%% Description: \n" 602 "%%% ----------------------------------------------------------------------\n", 603 [get_raises(X, ?IC_FLAG_TEMPLATE_2)]); 604emit_function_header(G, Fd, X, N, Name, {Extra, ExtraNo}, InP, Arity, OutP, 605 Reply, ReplyString, Vers) -> 606 emit(Fd, 607 "%%----------------------------------------------------------------------\n" 608 "%% Function : ~p/~p\n" 609 "%% Arguments : ~s\n", 610 [ic_util:to_atom(Name), (ExtraNo+Arity), Extra]), 611 ic_code:type_expand_all(G, N, X, Fd, ?TAB, InP), 612 case Reply of 613 ["ok"] -> 614 emit(Fd, "%% Returns : ReturnValue = ~s\n", [ReplyString]); 615 _ -> 616 emit(Fd, "%% Returns : ReturnValue = ~s\n", [ReplyString]), 617 ic_code:type_expand_all(G, N, X, Fd, " ", Reply) 618 end, 619 ic_code:type_expand_all(G, N, X, Fd, ?TAB, OutP), 620 emit(Fd, 621 "%% Raises : ~s\n" 622 "%% Description: \n" 623 "%%----------------------------------------------------------------------\n", 624 [get_raises(X, Vers)]). 625 626get_raises(#op{raises = []}, _Vers) -> 627 ""; 628get_raises(#op{raises = ExcList}, Vers) -> 629 get_raises2(ExcList, [], Vers); 630get_raises(_X, _Vers) -> 631 []. 632 633get_raises2([H], Acc, _Vers) -> 634 lists:flatten(lists:reverse([ic_util:to_colon(H)|Acc])); 635get_raises2([H|T], Acc, ?IC_FLAG_TEMPLATE_2) -> 636 get_raises2(T, ["\n%%% ", ic_util:to_colon(H) |Acc], 637 ?IC_FLAG_TEMPLATE_2); 638get_raises2([H|T], Acc, _Vers) -> 639 get_raises2(T, ["\n%% ", ic_util:to_colon(H) |Acc], _Vers). 640 641