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
23-module(ic_jbe).
24
25
26-export([do_gen/3, gen/3, emit_type_function/4]).
27
28
29
30-include("icforms.hrl").
31-include("ic.hrl").
32-include("ic_debug.hrl").
33-include_lib("stdlib/include/erl_compile.hrl").
34
35
36
37%%------------------------------------------------------------
38%%
39%% Entry point
40%%
41%%------------------------------------------------------------
42
43do_gen(G, _File, Form) ->
44    gen(G, [], Form).
45
46
47%%------------------------------------------------------------
48%%
49%% Generate the client side C stubs.
50%%
51%% Each module is generated to a separate file.
52%%
53%% Each function needs to generate a function head and
54%% a body. IDL parameters must be converted into C parameters.
55%%
56%%------------------------------------------------------------
57
58gen(G, N, [X|Xs]) when is_record(X, preproc) ->
59    NewG = handle_preproc(G, N, X#preproc.cat, X),
60    gen(NewG, N, Xs);
61
62gen(G, N, [X|Xs]) when is_record(X, module) ->
63    gen_module(G, N, X),
64    gen(G, N, Xs);
65
66gen(G, N, [X|Xs]) when is_record(X, interface) ->
67    gen_interface(G, N, X),
68    gen(G, N, Xs);
69
70gen(G, N, [X|Xs]) when is_record(X, const) ->
71    ic_constant_java:gen(G, N, X),
72    gen(G, N, Xs);
73
74gen(G, N, [X|Xs]) when is_record(X, op) ->
75    gen(G, N, Xs);
76
77gen(G, N, [X|Xs]) when is_record(X, attr) ->
78    gen(G, N, Xs);
79
80gen(G, N, [X|Xs]) when is_record(X, except) ->
81    gen_exception(G, N, X),
82    gen(G, N, Xs);
83
84gen(G, N, [X|Xs]) when is_record(X, enum) ->
85    ic_enum_java:gen(G, N, X),
86    gen(G, N, Xs);
87
88gen(G, N, [X|Xs]) when is_record(X, struct) ->
89    ic_struct_java:gen(G, N, X),
90    gen(G, N, Xs);
91
92gen(G, N, [X|Xs]) when is_record(X, union) ->
93    ic_union_java:gen(G, N, X),
94    gen(G, N, Xs);
95
96gen(G, N, [X|Xs]) when is_record(X, typedef) ->
97    gen_typedef(G, N, X),
98    gen(G, N, Xs);
99
100gen(G, N, [X|Xs]) when is_record(X, member) ->
101    %%?PRINTDEBUG2("gen member: ~p\n",[ic_forms:get_type(X)]),
102    gen_member(G, N, X),
103    gen(G, N, Xs);
104
105gen(G, N, [X|Xs]) when is_record(X, case_dcl) ->
106    %%?PRINTDEBUG2("gen case decl: ~p\n",[ic_forms:get_type(X)]),
107    gen(G, N, [ic_forms:get_type(X)]),
108    gen(G, N, Xs);
109
110gen(G, N, [_|Xs]) ->
111    gen(G, N, Xs);
112
113gen(_G, _N, []) ->
114    ok.
115
116
117%%%--------------------------------------------
118%%%
119%%%   Just generates the directory to host
120%%%   the module files
121%%%
122%%%--------------------------------------------
123
124gen_module(G, N, X) ->
125    case ic_genobj:do_gen(G) of
126
127	true -> %% Generate & register
128	    N1 = [ic_forms:get_id2(X) | N],
129	    %% Create directory
130	    ic_file:createJavaDirectory(G, N1),
131	    gen(G, N1, ic_forms:get_body(X));
132
133	false -> %% Register only
134	    N1 = [ic_forms:get_id2(X) | N],
135	    reg(G, N1, ic_forms:get_body(X))
136    end.
137
138reg(G, N, [X|_Xs]) when is_record(X, module) ->
139    reg(G, [ic_forms:get_id2(X) | N], ic_forms:get_body(X));
140
141reg(G, N, [X|_Xs]) when is_record(X, interface) ->
142    reg(G, [ic_forms:get_id2(X) | N], ic_forms:get_body(X));
143
144reg(G, N, [X|Xs]) when is_record(X, typedef) ->
145    Name = ic_util:to_dot(G,[ic_forms:get_java_id(X) | N]),
146    case X#typedef.type of
147	{scoped_id,_,_,_} ->
148	    {FullScopedName, _, _, _} =
149		ic_symtab:get_full_scoped_name(G, N, X#typedef.type),
150	    Type = ic_code:get_basetype(G, ic_util:to_dot(G,FullScopedName)),
151	    ic_code:insert_typedef(G, Name, Type);
152	_ ->
153	    ok
154    end,
155    reg(G, N, Xs);
156
157reg(G, N, [_|Xs]) ->
158    reg(G, N, Xs);
159
160reg(_G, _N, []) ->
161    ok.
162
163
164
165
166%%%----------------------------------------------
167%%%
168%%%   Generates the interface code
169%%%
170%%%----------------------------------------------
171
172gen_interface(G, N, X) ->
173    case ic_genobj:do_gen(G) of
174	true ->
175 	    G1 = ic_file:javaInterfaceFilePush(G, N, X),
176
177	    %% Generate Interface file
178	    InterfaceFd = ic_genobj:interfacefiled(G1),
179	    emit_interface(G1, N, X, InterfaceFd),
180
181	    %% Generate Helper file
182	    HelperFd = ic_genobj:helperfiled(G1),
183	    emit_helper(G1, N, X, HelperFd),
184
185	    %% Generate Holder file
186	    HolderFd = ic_genobj:holderfiled(G1),
187	    emit_holder(G1, N, X, HolderFd),
188
189	    %% Generate Stub file
190	    StubFd = ic_genobj:stubfiled(G1),
191	    emit_stub(G1,N,X,StubFd),  %<--------------------------------------------------- 1
192
193	    %% Generate Skeleton file
194	    SkelFd = ic_genobj:skelfiled(G1),
195	    emit_skel(G1, N, X, SkelFd),
196
197	    ic_file:javaInterfaceFilePop(G1);
198	false ->
199	    ok
200    end.
201
202
203
204
205%%%--------------------------------------------
206%%%
207%%%   Typedef redirection
208%%%
209%%%--------------------------------------------
210
211gen_typedef(G, N, X) ->
212    Name = ic_util:to_dot(G,[ic_forms:get_java_id(X) | N]),
213    case X#typedef.type of
214	{scoped_id,_,_,_} ->
215	    {FullScopedName, _, _, _} =
216		ic_symtab:get_full_scoped_name(G, N, X#typedef.type),
217	    Type = ic_code:get_basetype(G, ic_util:to_dot(G,FullScopedName)),
218	    ic_code:insert_typedef(G, Name, Type);
219	_ ->
220	    ok
221    end,
222    gen_typedef_1(G, N, X, ic_forms:get_body(X)).
223
224gen_typedef_1(G, N, X, Type) when is_record(Type, sequence) ->
225    ic_sequence_java:gen(G, N, Type, ic_forms:get_java_id(X));
226gen_typedef_1(G, N, X, Type) when is_record(Type, array) ->
227    ic_array_java:gen(G, N, X, Type);
228gen_typedef_1(G, N, X, _Type) ->
229    gen_typedef_2(G, N, X, X#typedef.id),
230    ok.
231
232gen_typedef_2(G, N, X, Type) when is_record(Type, array) ->
233    gen_typedef_1(G, N, X, Type);
234gen_typedef_2(G, N, X, Type) when is_list(Type) ->
235    case Type of
236	[] ->
237	    ok;
238	_ ->
239	    gen_typedef_2(G, N, X, hd(Type)),
240	    gen_typedef_2(G, N, X, tl(Type))
241    end;
242%gen_typedef_2(G, N, X, Type) -> %% Generating Helpers for typedef
243%                                %% Stoped due to compatibility problems
244%                                %% with erl_genserv backend
245%    case ic_java_type:isBasicType(G,N,X#typedef.type) of
246%	true ->
247%	    ok;
248%	false ->
249%	    case ic_forms:get_type_code(G,N,X#typedef.type) of
250%		{'tk_struct', _, _, _} ->
251%		    ic_struct_java:gen(G, N, X);
252%		{'tk_sequence',_,_} ->
253%		    ic_sequence_java:gen(G, N, X, ic_forms:get_java_id(X)),
254%		    ok;
255%		_ ->
256%		    ok
257%	    end
258%    end;
259gen_typedef_2(_G, _N, _X, _Type) ->
260    ok.
261
262
263
264%%%--------------------------------------------
265%%%
266%%%   Member redirection
267%%%
268%%%--------------------------------------------
269
270gen_member(G, N, X) ->
271    gen_member_1(G, N, X, [X#member.type]),
272    gen_member_2(G, N, X, X#member.id).
273
274
275gen_member_1(_G, _N, _X, []) ->
276    ok;
277
278gen_member_1(G, N, X, [T|Ts]) when is_record(T, sequence) ->
279    ic_sequence_java:gen(G, N, T, ic_forms:get_java_id(X)),
280    gen_member_1(G, N, X, Ts);
281
282gen_member_1(G, N, X, [T|Ts]) ->
283    gen(G,N,[T]),
284    gen_member_1(G,N,X,Ts).
285
286
287gen_member_2(_G, _N, _X, []) ->
288    ok;
289
290gen_member_2(G, N, X, [T|Ts]) when is_record(T, array) -> %% BUG !
291    ic_array_java:gen(G, N, X, T),
292    gen_member_2(G, N, X, Ts);
293
294gen_member_2(G, N, X, [_T|Ts]) ->
295    gen_member_2(G, N, X, Ts).
296
297
298
299gen_exception(_G, N, X) ->
300    io:format("Warning : Exceptions not supported for java mapping, ~p ignored\n",
301	     [ic_util:to_colon([ic_forms:get_java_id(X)|N])]),
302    ok.
303
304
305
306%%%-----------------------------------------------------
307%%%
308%%%  Interface file generation
309%%%
310%%%-----------------------------------------------------
311
312emit_interface(G, N, X, Fd) ->
313    Interface = ic_forms:get_java_id(X), %% Java Interface Name
314    IFCName = ic_forms:get_id2(X), %% Internal Interface Name
315
316    ic_codegen:emit(Fd, "public interface ~s {\n\n",[Interface]),
317    Body = ic_forms:get_body(X),
318
319    %% Generate type declarations inside interface
320    gen(G, [IFCName |N], Body),
321
322    lists:foreach(fun({_Name, Body1}) ->
323			  emit_interface_prototypes(G, [IFCName|N], Body1, Fd) end,
324		  [{x, Body} | X#interface.inherit_body]),
325
326    ic_codegen:emit(Fd, "}\n\n").
327
328
329emit_interface_prototypes(G, N, [X |Xs], Fd) when is_record(X, op) ->
330
331    {_, ArgNames, TypeList} = extract_info(G, N, X),
332    {R, ParameterTypes, _} = TypeList,
333
334    OpName = ic_forms:get_java_id(X),
335    RT = ic_java_type:getParamType(G,N,R,ret),
336    PL = ic_util:mk_list(gen_par_list(G, N, X, ParameterTypes,ArgNames)),
337
338    ic_codegen:emit(Fd, "/*\n"),
339    ic_codegen:emit(Fd, " * Operation ~p interface functions \n", [ic_util:to_colon([OpName|N])]),
340    ic_codegen:emit(Fd, " */\n\n"),
341
342    ic_codegen:emit(Fd, "~s ~s(~s)\n",[RT, OpName, PL]),
343    ic_codegen:emit(Fd, "     throws java.lang.Exception;\n\n\n"),
344
345    emit_interface_prototypes(G, N, Xs, Fd);
346emit_interface_prototypes(G, N, [X |Xs], Fd) when is_record(X, attr) ->
347    ic_attribute_java:emit_attribute_prototype(G, N, X, Fd),
348    emit_interface_prototypes(G, N, Xs, Fd);
349emit_interface_prototypes(G, N, [_X|Xs], Fd) ->
350    emit_interface_prototypes(G, N, Xs, Fd);
351emit_interface_prototypes(_G, _N, [], _Fd) -> ok.
352
353
354
355
356%%%-----------------------------------------------------
357%%%
358%%%  Holder file generation
359%%%
360%%%-----------------------------------------------------
361
362emit_holder(_G, N, X, Fd) ->
363    InterfaceName = ic_forms:get_java_id(X),
364    FullInterfaceName = ic_util:to_dot([InterfaceName|N]),
365
366    ic_codegen:emit(Fd, "public final class ~sHolder {\n\n",[InterfaceName]),
367
368    ic_codegen:emit(Fd, "    // Instance variable\n"),
369    ic_codegen:emit(Fd, "    public ~s value;\n\n",[FullInterfaceName]),
370
371    ic_codegen:emit(Fd, "    // Constructors\n"),
372    ic_codegen:emit(Fd, "    public ~sHolder() {\n",[InterfaceName]),
373    ic_codegen:emit(Fd, "        this(null);\n"),
374    ic_codegen:emit(Fd, "    }\n\n"),
375
376    ic_codegen:emit(Fd, "    public ~sHolder(~s _arg) {\n",[InterfaceName, FullInterfaceName]),
377    ic_codegen:emit(Fd, "        value = _arg;\n"),
378    ic_codegen:emit(Fd, "    }\n\n"),
379
380    ic_codegen:emit(Fd, "    public void _marshal() {\n"),
381    ic_codegen:emit(Fd, "    }\n\n"),
382
383    ic_codegen:emit(Fd, "    public void _unmarshal() {\n"),
384    ic_codegen:emit(Fd, "    }\n\n"),
385
386    ic_codegen:emit(Fd, "}\n\n").
387
388
389
390
391%%%-----------------------------------------------------
392%%%
393%%%  Helper file generation
394%%%
395%%%-----------------------------------------------------
396emit_helper(G, N, X, Fd) ->
397    InterfaceName = ic_forms:get_java_id(X),
398    FullInterfaceName = ic_util:to_dot([InterfaceName|N]),
399
400    ic_codegen:emit(Fd, "public final class ~sHelper {\n\n",[InterfaceName]),
401
402    ic_codegen:emit(Fd, "    // Constructor\n"),
403    ic_codegen:emit(Fd, "    public ~sHelper() {\n",[InterfaceName]),
404    ic_codegen:emit(Fd, "    }\n\n"),
405
406    ic_codegen:emit(Fd, "    public static void _marshal() {\n"),
407    ic_codegen:emit(Fd, "        // Writing the object to the message\n"),
408    ic_codegen:emit(Fd, "    }\n\n"),
409
410    ic_codegen:emit(Fd, "    public static ~s _unmarshal() {\n",[FullInterfaceName]),
411    ic_codegen:emit(Fd, "        // Reading the object from the message\n"),
412    ic_codegen:emit(Fd, "        return null;\n"),
413    ic_codegen:emit(Fd, "    }\n\n"),
414
415    ic_codegen:emit(Fd, "    public static java.lang.String id() {\n"),
416    ic_codegen:emit(Fd, "        return ~p;\n",[ictk:get_IR_ID(G, N, X)]),
417    ic_codegen:emit(Fd, "    }\n\n"),
418
419    ic_codegen:emit(Fd, "}\n\n").
420
421
422
423
424%%%-----------------------------------------------------
425%%%
426%%%  Stub file generation
427%%%
428%%%-----------------------------------------------------
429
430emit_stub(G, N, X, Fd) ->
431    InterfaceName = ic_forms:get_java_id(X), %% Java Interface Name
432    IFCName = ic_forms:get_id2(X),           %% Internal Interface Name
433
434    FullInterfaceName = ic_util:to_dot([InterfaceName|N]),
435    Body = ic_forms:get_body(X),
436
437    ic_codegen:emit(Fd, "public class _~sStub implements ~s {\n\n",
438		    [InterfaceName,FullInterfaceName]),
439
440    ic_codegen:emit(Fd, "    // Client data\n"),
441    ic_codegen:emit(Fd, "    public ~sEnvironment _env;\n\n",[?ICPACKAGE]),
442
443    ic_codegen:emit(Fd, "    // Constructors\n"),
444    ic_codegen:emit(Fd, "    public _~sStub(~sOtpSelf _self,\n",[InterfaceName,?ERLANGPACKAGE]),
445    ic_codegen:emit(Fd, "                       ~sOtpPeer _peer,\n",[?ERLANGPACKAGE]),
446    ic_codegen:emit(Fd, "                       java.lang.Object _server) throws java.lang.Exception {\n\n"),
447
448    ic_codegen:emit(Fd, "      _env =\n"),
449    ic_codegen:emit(Fd, "         new ~sEnvironment(_self, _peer, _server);\n",[?ICPACKAGE]),
450    ic_codegen:emit(Fd, "      _env.connect();\n"),
451    ic_codegen:emit(Fd, "    }\n\n"),
452
453    ic_codegen:emit(Fd, "    public _~sStub(java.lang.String _selfN,\n",[InterfaceName]),
454    ic_codegen:emit(Fd, "                       java.lang.String _peerN,\n"),
455    ic_codegen:emit(Fd, "                       java.lang.String _cookie,\n"),
456    ic_codegen:emit(Fd, "                       java.lang.Object _server) throws java.lang.Exception {\n\n"),
457    ic_codegen:emit(Fd, "      _env =\n"),
458    ic_codegen:emit(Fd, "         new ~sEnvironment(_selfN, _peerN, _cookie, _server);\n",[?ICPACKAGE]),
459    ic_codegen:emit(Fd, "      _env.connect();\n"),
460    ic_codegen:emit(Fd, "    }\n\n"),
461
462    ic_codegen:emit(Fd, "    public _~sStub(~sOtpConnection _connection,\n",[InterfaceName, ?ERLANGPACKAGE]),
463    ic_codegen:emit(Fd, "                       java.lang.Object _server) throws java.lang.Exception {\n\n"),
464    ic_codegen:emit(Fd, "      _env =\n"),
465    ic_codegen:emit(Fd, "         new ~sEnvironment(_connection, _server);\n",[?ICPACKAGE]),
466    ic_codegen:emit(Fd, "      _env.connect();\n"),
467    ic_codegen:emit(Fd, "    }\n\n"),
468
469    emit_message_reference_extraction(Fd),
470
471    emit_servers_object_access(Fd),
472
473    emit_client_connection_close(Fd),
474
475    emit_client_connection_reconnect(Fd),
476
477    emit_client_destroy(Fd),
478
479    lists:foreach(fun({_Name, Body1}) ->
480			  emit_op_implementation(G, [IFCName|N], Body1, Fd) end,
481		  [{x, Body} | X#interface.inherit_body]),
482
483    ic_codegen:emit(Fd, "}\n\n").
484
485
486emit_op_implementation(G, N, [X |Xs], Fd) when is_record(X, op) ->
487
488    WireOpName = ic_forms:get_id2(X),
489    OpName = ic_forms:get_java_id(WireOpName),
490    {_, ArgNames, TypeList} = extract_info(G, N, X),
491    {R, ParamTypes, _} = TypeList,
492
493    RT = ic_java_type:getParamType(G,N,R,ret),
494    PL = ic_util:mk_list(gen_par_list(G, N, X, ParamTypes, ArgNames)),
495    CMCPL = ic_util:mk_list(gen_client_marshal_call_par_list(ArgNames)),
496
497    ic_codegen:emit(Fd, "    // Operation ~p implementation\n", [ic_util:to_colon([WireOpName|N])]),
498    ic_codegen:emit(Fd, "    public ~s ~s(~s)\n", [RT, OpName, PL]),
499    ic_codegen:emit(Fd, "      throws java.lang.Exception {\n\n"),
500
501    %% Function marshal call
502    ic_codegen:emit(Fd, "      // Calling the marshal function\n"),
503
504    case CMCPL of
505	"" ->
506	    ic_codegen:emit(Fd, "      _~s_marshal(_env);\n\n",[OpName]);
507	_ ->
508	    ic_codegen:emit(Fd, "      _~s_marshal(_env, ~s);\n\n",[OpName, CMCPL])
509    end,
510
511    %% Sending call
512    ic_codegen:emit(Fd, "      // Message send\n"),
513    ic_codegen:emit(Fd, "      _env.send();\n\n"),
514
515    case ic_forms:is_oneway(X) of
516	true ->
517	    ok;
518	false ->
519	    %% Receiving return values
520	    ic_codegen:emit(Fd, "      // Message receive\n"),
521	    ic_codegen:emit(Fd, "      _env.receive();\n\n"),
522
523	    %% Function unmarshal call
524	    case RT of
525		"void" ->
526		    case ic_util:mk_list(gen_client_unmarshal_call_par_list(ArgNames)) of
527			"" ->
528			    ic_codegen:emit(Fd, "      // Calling the unmarshal function\n"),
529			    ic_codegen:emit(Fd, "      _~s_unmarshal(_env);\n",
530					    [OpName]);
531			UMCPL ->
532			    ic_codegen:emit(Fd, "      // Calling the unmarshal function\n"),
533			    ic_codegen:emit(Fd, "      _~s_unmarshal(_env, ~s);\n",
534					    [OpName,UMCPL])
535		    end;
536		_ ->
537		    ic_codegen:emit(Fd, "      // Calling the unmarshal function\n"),
538		    case ic_util:mk_list(gen_client_unmarshal_call_par_list(ArgNames)) of
539			"" ->
540			    ic_codegen:emit(Fd, "      return _~s_unmarshal(_env);\n",
541					    [OpName]);
542			UMCPL ->
543			    ic_codegen:emit(Fd, "      return _~s_unmarshal(_env, ~s);\n",
544					    [OpName,UMCPL])
545		    end
546	    end
547    end,
548    ic_codegen:emit(Fd, "    }\n\n"),
549
550    %% Marshalling
551    emit_op_marshal(G, N, X, Fd),
552
553    %% UnMarshalling
554    emit_op_unmarshal(G, N, X, Fd),
555    ic_codegen:emit(Fd, "\n"),
556
557    emit_op_implementation(G, N, Xs, Fd);
558emit_op_implementation(G, N, [X |Xs], Fd) when is_record(X, attr) ->
559    ic_attribute_java:emit_attribute_stub_code(G, N, X, Fd),
560    emit_op_implementation(G, N, Xs, Fd);
561emit_op_implementation(G, N, [_X|Xs], Fd) ->
562    emit_op_implementation(G, N, Xs, Fd);
563emit_op_implementation(_G, _N, [], _Fd) -> ok.
564
565
566
567
568
569%%---------------------------------------
570%%
571%%  Marshal operation generation
572%%
573%%---------------------------------------
574
575emit_op_marshal(G, N, X, Fd) ->
576    WireOpName = ic_forms:get_id2(X),
577    OpName = ic_forms:get_java_id(WireOpName),
578    {_, ArgNames, TypeList} = extract_info(G, N, X),
579    {_R, ParamTypes, _} = TypeList,
580
581    PL = ic_util:mk_list(gen_marshal_par_list(G, N, X, ParamTypes, ArgNames)),
582
583    ic_codegen:emit(Fd, "    // Marshal operation for ~p\n", [OpName]),
584    case PL of
585	"" ->
586	    ic_codegen:emit(Fd, "    public static void _~s_marshal(~sEnvironment __env)\n",
587			    [OpName, ?ICPACKAGE]),
588	    ic_codegen:emit(Fd, "      throws java.lang.Exception {\n\n");
589	_ ->
590	    ic_codegen:emit(Fd, "    public static void _~s_marshal(~sEnvironment __env, ~s)\n",
591			    [OpName, ?ICPACKAGE, PL]),
592	    ic_codegen:emit(Fd, "      throws java.lang.Exception {\n\n")
593    end,
594    %% Message encoding
595    emit_op_encode(G, N, X, OpName, WireOpName, ParamTypes, ArgNames, Fd),
596
597    ic_codegen:emit(Fd, "    }\n\n").
598
599
600emit_op_encode(G, N, X, _OpN, WOpN, ParamTypes, ArgNames, Fd) ->
601
602    OpCallName = case ic_options:get_opt(G, scoped_op_calls) of
603		     true ->
604			 ic_util:to_undersc([WOpN|N]);
605		     false ->
606			 WOpN
607		 end,
608
609    SendParamNr = count_client_send(ArgNames),
610
611    ic_codegen:emit(Fd, "      ~sOtpOutputStream __os = __env.getOs();\n\n",
612		    [?ERLANGPACKAGE]),
613
614    case ic_forms:is_oneway(X) of
615	true ->
616	    %% Initiating call tuple
617	    ic_codegen:emit(Fd, "      // Message header assembly\n"),
618	    ic_codegen:emit(Fd, "      __os.reset();\n"),
619	    ic_codegen:emit(Fd, "      __os.write_tuple_head(2);\n"),
620	    ic_codegen:emit(Fd, "      __os.write_atom(\"$gen_cast\");\n\n");
621	false ->
622	    %% Initiating call tuple
623	    ic_codegen:emit(Fd, "      // Message header assembly\n"),
624	    ic_codegen:emit(Fd, "      __os.reset();\n"),
625	    ic_codegen:emit(Fd, "      __os.write_tuple_head(3);\n"),
626	    ic_codegen:emit(Fd, "      __os.write_atom(\"$gen_call\");\n\n"),
627
628	    %% Initiating call identity tuple
629	    ic_codegen:emit(Fd, "      // Message identity part creation\n"),
630	    ic_codegen:emit(Fd, "      __os.write_tuple_head(2);\n"),
631	    ic_codegen:emit(Fd, "      __env.write_client_pid();\n"),
632	    ic_codegen:emit(Fd, "      __env.write_client_ref();\n\n")
633    end,
634
635    %% Operation part initializations
636    case SendParamNr > 0 of
637	true ->
638	    ic_codegen:emit(Fd, "      // Operation attribute creation\n"),
639	    ic_codegen:emit(Fd, "      __os.write_tuple_head(~p);\n", [SendParamNr+1]),
640	    ic_codegen:emit(Fd, "      __os.write_atom(~p);\n", [OpCallName]),
641	    emit_op_encode_loop(G, N, X, ParamTypes, ArgNames, 1, Fd);
642	false -> %% No in/inout paramaters
643	    ic_codegen:emit(Fd, "      __os.write_atom(~p);\n", [OpCallName])
644    end.
645
646
647
648emit_op_encode_loop(_,_,_,_,[],_,_Fd) ->
649    ok;
650emit_op_encode_loop(G, N, X, [_Type|Types],[{out, _Arg}|Args], Counter, Fd) ->
651    emit_op_encode_loop(G, N, X, Types, Args, Counter, Fd);
652emit_op_encode_loop(G, N, X, [Type|Types], [{inout, Arg}|Args], Counter, Fd) ->
653    case ic_java_type:isBasicType(G, N, Type) of
654	true ->
655	    ic_codegen:emit(Fd, "      __os~s(~s.value);\n",
656			    [ic_java_type:marshalFun(G, N, X, Type),Arg]);
657	false ->
658	    ic_codegen:emit(Fd, "      ~s(__os, ~s.value);\n",
659			    [ic_java_type:marshalFun(G, N, X, Type),Arg])
660    end,
661    emit_op_encode_loop(G, N, X, Types, Args, Counter+1, Fd);
662emit_op_encode_loop(G, N, X, [Type|Types], [{in, Arg}|Args], Counter, Fd) ->
663    case ic_java_type:isBasicType(G, N, Type) of
664	true ->
665	    ic_codegen:emit(Fd, "      __os~s(~s);\n",
666			    [ic_java_type:marshalFun(G, N, X, Type),Arg]);
667	false ->
668	    ic_codegen:emit(Fd, "      ~s(__os, ~s);\n",
669			    [ic_java_type:marshalFun(G, N, X, Type),Arg])
670    end,
671    emit_op_encode_loop(G, N, X, Types, Args, Counter+1, Fd).
672
673
674
675
676
677
678%%-------------------------------------
679%%
680%%  UnMarshal operation generation
681%%
682%%-------------------------------------
683
684emit_op_unmarshal(G, N, X, Fd) ->
685    case ic_forms:is_oneway(X) of
686	true ->
687	    ok;
688	false ->
689	    OpName = ic_forms:get_java_id(X),
690	    {_, ArgNames, TypeList} = extract_info(G, N, X),
691	    {R, ParamTypes, _} = TypeList,
692
693	    RT = ic_java_type:getParamType(G,N,R,ret),
694	    PL = ic_util:mk_list(gen_unmarshal_par_list(G, N, X, ParamTypes, ArgNames)),
695
696	    case PL of
697		"" ->
698		    case RT of
699			"void" ->
700			    ic_codegen:emit(Fd, "    // Unmarshal operation for ~p\n", [OpName]),
701			    ic_codegen:emit(Fd, "    public static void _~s_unmarshal(~sEnvironment __env)\n",
702					    [OpName, ?ICPACKAGE]),
703			    ic_codegen:emit(Fd, "      throws java.lang.Exception {\n\n"),
704			    ic_codegen:emit(Fd, "        __env.getIs().read_atom();\n"),
705			    ic_codegen:emit(Fd, "    }\n\n");
706			_ ->
707			    ic_codegen:emit(Fd, "    // Unmarshal operation for ~p\n", [OpName]),
708			    ic_codegen:emit(Fd, "    public static ~s _~s_unmarshal(~sEnvironment __env)\n",
709					    [RT, OpName, ?ICPACKAGE]),
710			    ic_codegen:emit(Fd, "      throws java.lang.Exception {\n\n"),
711
712			    ic_codegen:emit(Fd, "      // Get input stream\n"),
713			    ic_codegen:emit(Fd, "      ~sOtpInputStream __is = __env.getIs();\n\n",
714					    [?ERLANGPACKAGE]),
715
716			    emit_op_decode(G, N, X, R, RT, ParamTypes, ArgNames, Fd),
717			    ic_codegen:emit(Fd, "    }\n\n")
718		    end;
719		_ ->
720		    ic_codegen:emit(Fd, "    // Unmarshal operation for ~p\n", [OpName]),
721		    ic_codegen:emit(Fd, "    public static ~s _~s_unmarshal(~sEnvironment __env, ~s)\n",
722				    [RT, OpName, ?ICPACKAGE, PL]),
723		    ic_codegen:emit(Fd, "      throws java.lang.Exception {\n\n"),
724
725		    ic_codegen:emit(Fd, "      // Get input stream\n"),
726		    ic_codegen:emit(Fd, "      ~sOtpInputStream __is = __env.getIs();\n\n",
727				    [?ERLANGPACKAGE]),
728
729		    emit_op_decode(G, N, X, R, RT, ParamTypes, ArgNames, Fd),
730		    ic_codegen:emit(Fd, "    }\n\n")
731	    end
732    end.
733
734
735emit_op_decode(G, N, X, R, RT, ParamTypes, ArgNames, Fd) ->
736    ReceiveNr = count_client_receive(ArgNames),
737
738    case RT of
739	"void" ->
740	    case ReceiveNr > 0 of
741		true ->
742		    ic_codegen:emit(Fd, "      // Extracting output values\n"),
743		    ic_codegen:emit(Fd, "      __is.read_tuple_head();\n"),
744		    ic_codegen:emit(Fd, "      __is.read_atom();\n"),
745		    emit_op_decode_loop(G, N, X, ParamTypes, ArgNames, 1, Fd);
746		false ->
747		    ic_codegen:emit(Fd, "      __is.read_atom();\n")
748	    end;
749	_ ->
750	    case ReceiveNr > 0 of
751		true ->
752		    ic_codegen:emit(Fd, "      // Extracting return/output values\n"),
753		    ic_codegen:emit(Fd, "      __is.read_tuple_head();\n"),
754		    case ic_java_type:isBasicType(G,N,R) of
755			true ->
756			    ic_codegen:emit(Fd, "      ~s _result = __is~s;\n",
757					    [RT,ic_java_type:unMarshalFun(G, N, X, R)]);
758			false ->
759			    ic_codegen:emit(Fd, "      ~s _result = ~s.unmarshal(__is);\n",
760					    [RT, ic_java_type:getUnmarshalType(G,N,X,R)])
761		    end,
762		    emit_op_decode_loop(G, N, X, ParamTypes, ArgNames, 1, Fd),
763
764		    ic_codegen:nl(Fd),
765		    ic_codegen:emit(Fd, "      return _result;\n");
766		false ->
767		    ic_codegen:emit(Fd, "      // Extracting return value\n"),
768		    case ic_java_type:isBasicType(G,N,R) of
769			true ->
770			    ic_codegen:emit(Fd, "      return __is~s;\n",
771					    [ic_java_type:unMarshalFun(G, N, X, R)]);
772			false ->
773			    ic_codegen:emit(Fd, "      return ~s.unmarshal(__is);\n",
774					    [ic_java_type:getUnmarshalType(G,N,X,R)])
775		    end
776	    end
777    end.
778
779emit_op_decode_loop(_,_,_,_,[],_,_Fd) ->
780    ok;
781emit_op_decode_loop(G, N, X, [_Type|Types], [{in, _Arg}|Args], Counter, Fd) ->
782    emit_op_decode_loop(G, N, X, Types, Args, Counter, Fd);
783emit_op_decode_loop(G, N, X, [Type|Types], [{_, Arg}|Args], Counter, Fd) ->
784    case ic_java_type:isBasicType(G,N,Type) of
785	true ->
786	    ic_codegen:emit(Fd, "      ~s.value = __is~s;\n",
787			    [Arg,
788			     ic_java_type:unMarshalFun(G, N, X, Type)]);
789	false ->
790	    ic_codegen:emit(Fd, "      ~s.value = ~s.unmarshal(__is);\n",
791			    [Arg,
792			     ic_java_type:getUnmarshalType(G, N, X, Type)])
793    end,
794    emit_op_decode_loop(G, N, X, Types, Args, Counter+1, Fd).
795
796
797
798emit_message_reference_extraction(Fd) ->
799    ic_codegen:emit(Fd, "    // Returns call reference\n"),
800    ic_codegen:emit(Fd, "    public ~sOtpErlangRef __getRef()\n",
801		   [?ERLANGPACKAGE]),
802    ic_codegen:emit(Fd, "      throws java.lang.Exception {\n"),
803    ic_codegen:emit(Fd, "        return _env.received_ref();\n"),
804    ic_codegen:emit(Fd, "    }\n\n").
805
806emit_servers_object_access(Fd) ->
807    ic_codegen:emit(Fd, "    // Returns the server\n"),
808    ic_codegen:emit(Fd, "    public java.lang.Object __server() {\n"),
809    ic_codegen:emit(Fd, "      return _env.server();\n"),
810    ic_codegen:emit(Fd, "    }\n\n").
811
812emit_client_connection_close(Fd) ->
813    ic_codegen:emit(Fd, "    // Closes connection\n"),
814    ic_codegen:emit(Fd, "    public void __disconnect() {\n"),
815    ic_codegen:emit(Fd, "      _env.disconnect();\n"),
816    ic_codegen:emit(Fd, "    }\n\n").
817
818emit_client_connection_reconnect(Fd) ->
819    ic_codegen:emit(Fd, "    // Reconnects client\n"),
820    ic_codegen:emit(Fd, "    public void __reconnect()\n"),
821    ic_codegen:emit(Fd, "      throws java.lang.Exception {\n"),
822    ic_codegen:emit(Fd, "      _env.reconnect();\n"),
823    ic_codegen:emit(Fd, "    }\n\n").
824
825emit_client_destroy(Fd) ->
826    ic_codegen:emit(Fd, "    // Destroy server\n"),
827    ic_codegen:emit(Fd, "    public void __stop()\n"),
828    ic_codegen:emit(Fd, "      throws java.lang.Exception {\n"),
829    ic_codegen:emit(Fd, "      _env.client_stop_server();\n"),
830    ic_codegen:emit(Fd, "    }\n\n").
831
832
833
834%%%----------------------------------------------------
835%%%
836%%%   Generates the server code
837%%%
838%%%----------------------------------------------------
839
840emit_skel(G, N, X, Fd) ->
841    InterfaceName = ic_forms:get_java_id(X),
842    FullInterfaceName = ic_util:to_dot([InterfaceName|N]),
843
844    ic_codegen:emit(Fd, "public abstract class _~sImplBase implements ~s {\n\n",
845		    [InterfaceName,FullInterfaceName]),
846
847    ic_codegen:emit(Fd, "    // Server data\n"),
848    ic_codegen:emit(Fd, "    protected ~sEnvironment _env = null;\n\n",[?ICPACKAGE]),
849
850    ic_codegen:emit(Fd, "    // Constructors\n"),
851    ic_codegen:emit(Fd, "    public _~sImplBase() {\n",[InterfaceName]),
852    ic_codegen:emit(Fd, "    }\n\n"),
853
854    emit_caller_pid(G, N, X, Fd),
855
856    %% Emit operation dictionary
857    emit_dictionary(G, N, X, Fd),
858
859    %% Emit server switch
860    emit_server_switch(G, N, X, Fd),
861
862    ic_codegen:emit(Fd, "}\n").
863
864
865emit_server_switch(G, N, X, Fd) ->
866
867    IFCName = ic_forms:get_id2(X),           %% Internal Interface Name
868    Body = ic_forms:get_body(X),
869    Counter = 0,
870
871    ic_codegen:emit(Fd, "    // Operation invokation\n"),
872    ic_codegen:emit(Fd, "    public ~sOtpOutputStream invoke(~sOtpInputStream _in)\n",
873		    [?ERLANGPACKAGE,?ERLANGPACKAGE]),
874    ic_codegen:emit(Fd, "      throws java.lang.Exception {\n\n"),
875
876    ic_codegen:emit(Fd, "       // Create a new environment if needed\n"),
877    ic_codegen:emit(Fd, "      	if (_env == null)\n"),
878    ic_codegen:emit(Fd, "      	  _env = new com.ericsson.otp.ic.Environment();\n\n"),
879
880    ic_codegen:emit(Fd, "       // Unmarshal head\n"),
881    ic_codegen:emit(Fd, "      	_env.uHead(_in);\n\n"),
882
883    ic_codegen:emit(Fd, "      	// Switch over operation\n"),
884    ic_codegen:emit(Fd, "      	return __switch(_env);\n"),
885
886    ic_codegen:emit(Fd, "    }\n\n"),
887
888
889    ic_codegen:emit(Fd, "     // Operation switch\n"),
890    ic_codegen:emit(Fd, "     public ~sOtpOutputStream __switch(~sEnvironment __env)\n", [?ERLANGPACKAGE,?ICPACKAGE]),
891    ic_codegen:emit(Fd, "       throws java.lang.Exception {\n\n"),
892
893    ic_codegen:emit(Fd, "       // Setup streams and operation label\n"),
894    ic_codegen:emit(Fd, "       ~sOtpOutputStream __os = __env.getOs();\n",[?ERLANGPACKAGE]),
895    ic_codegen:emit(Fd, "       __os.reset();\n"),
896    ic_codegen:emit(Fd, "       int __label = __env.uLabel(__operations);\n\n"),
897
898    ic_codegen:emit(Fd, "       // Switch over operation\n"),
899    ic_codegen:emit(Fd, "       switch(__label) {\n\n"),
900
901    OpNr = emit_server_op_switch_loop(G,
902				      [IFCName|N],
903				      [{x, Body} | X#interface.inherit_body],
904				      Counter,
905				      Fd),
906
907    ic_codegen:emit(Fd, "       case ~p: { // Standard stop operation\n\n",[OpNr]),
908    ic_codegen:emit(Fd, "         __env.server_stop_server();\n\n"),
909    ic_codegen:emit(Fd, "       } break;\n\n"),
910
911    ic_codegen:emit(Fd, "       default: // It will never come down here \n"),
912    ic_codegen:emit(Fd, "         throw new java.lang.Exception(\"BAD OPERATION\");\n\n", []),
913
914    ic_codegen:emit(Fd, "      }\n\n"),
915
916    ic_codegen:emit(Fd, "      if(__os.count() > 0)\n"),
917    ic_codegen:emit(Fd, "        return __os;\n\n"),
918
919    ic_codegen:emit(Fd, "      return null;\n"),
920    ic_codegen:emit(Fd, "    }\n\n").
921
922
923
924emit_server_op_switch_loop(_G, _N, [], C, _Fd) ->
925    C;
926emit_server_op_switch_loop(G, N, [{_,X}|Xs], C, Fd) ->
927    C1 = emit_server_op_switch(G, N, X, C, Fd),
928    emit_server_op_switch_loop(G, N, Xs, C1, Fd).
929
930
931emit_server_op_switch(G, N, [X|Xs], C, Fd) when is_record(X, op) ->
932
933    OpName = ic_forms:get_java_id(X),
934
935    ic_codegen:emit(Fd, "       case ~p:  {  // Operation ~s\n\n",[C,ic_util:to_dot([OpName|N])]),
936
937    emit_invoke(G, N, X, Fd),
938
939    ic_codegen:emit(Fd, "       } break;\n\n"),
940
941    emit_server_op_switch(G, N, Xs, C+1, Fd);
942emit_server_op_switch(G, N, [X |Xs], C, Fd) when is_record(X, attr) ->
943    C1 = ic_attribute_java:emit_attribute_switch_case(G,N,X,Fd,C),
944    emit_server_op_switch(G, N, Xs, C1, Fd);
945emit_server_op_switch(G, N, [_X|Xs], C, Fd) ->
946    emit_server_op_switch(G, N, Xs, C, Fd);
947emit_server_op_switch(_G, _N, [], C, _Fd) ->
948    C.
949
950
951emit_caller_pid(_G, _N, _X, Fd) ->
952    ic_codegen:emit(Fd, "    // Extracts caller identity\n"),
953    ic_codegen:emit(Fd, "    public ~sOtpErlangPid __getCallerPid() {\n", [?ERLANGPACKAGE]),
954    ic_codegen:emit(Fd, "      return _env.getScaller();\n"),
955    ic_codegen:emit(Fd, "    }\n\n"),
956
957    ic_codegen:emit(Fd, "    public ~sOtpErlangPid __getCallerPid(~sEnvironment __env) {\n",
958		    [?ERLANGPACKAGE, ?ICPACKAGE]),
959    ic_codegen:emit(Fd, "      return __env.getScaller();\n"),
960    ic_codegen:emit(Fd, "    }\n\n"),
961
962    ic_codegen:emit(Fd, "    public boolean __isStopped() {\n"),
963    ic_codegen:emit(Fd, "      return _env.isStopped();\n"),
964    ic_codegen:emit(Fd, "    }\n\n"),
965
966    ic_codegen:emit(Fd, "    public boolean __isStopped(~sEnvironment __env) {\n",
967		    [?ICPACKAGE]),
968    ic_codegen:emit(Fd, "      return __env.isStopped();\n"),
969    ic_codegen:emit(Fd, "    }\n\n").
970
971
972
973%% Creates an operation dictionary
974emit_dictionary(G, N, X, Fd) ->
975
976    Counter = 0,
977    Body = ic_forms:get_body(X),
978
979    ic_codegen:emit(Fd, "    // Operation dictionary\n"),
980    ic_codegen:emit(Fd, "    private static java.util.Dictionary __operations = new java.util.Hashtable();\n"),
981    ic_codegen:emit(Fd, "    static {\n"),
982
983    emit_dictionary_loop(G,
984			 [ic_forms:get_id2(X)|N],
985			 [{x, Body} | X#interface.inherit_body],
986			 Counter,
987			 Fd),
988
989    ic_codegen:emit(Fd, "    }\n\n"),
990
991    ic_codegen:emit(Fd, "    // Operation dictionary access\n"),
992    ic_codegen:emit(Fd, "    public static java.util.Dictionary __operations() {\n"),
993    ic_codegen:emit(Fd, "      return __operations;\n"),
994    ic_codegen:emit(Fd, "    }\n\n").
995
996
997
998
999emit_dictionary_loop(_G, _N, [], C, Fd) ->
1000    ic_codegen:emit(Fd, "      __operations.put(~p, new java.lang.Integer(~p));\n",
1001		    ["stop",C]);
1002emit_dictionary_loop(G, N, [{_,X}|Xs], C, Fd) ->
1003    C1 = emit_dictionary(G, N, X, C, Fd),
1004    emit_dictionary_loop(G, N, Xs, C1, Fd).
1005
1006
1007emit_dictionary(G, N, [X|Xs], C, Fd) when is_record(X, op) ->
1008
1009    OpName = case ic_options:get_opt(G, scoped_op_calls) of
1010		 true ->
1011		     ic_util:to_undersc([ic_forms:get_id2(X)|N]);
1012		 false ->
1013		     ic_forms:get_id2(X)
1014	     end,
1015
1016    ic_codegen:emit(Fd, "      __operations.put(~p, new java.lang.Integer(~p));\n",
1017		    [OpName,C]),
1018    emit_dictionary(G, N, Xs, C+1, Fd);
1019
1020emit_dictionary(G, N, [X |Xs], C, Fd) when is_record(X, attr) ->
1021    C1 = ic_attribute_java:emit_atrribute_on_dictionary(G, N, X, Fd, C),
1022    emit_dictionary(G, N, Xs, C1, Fd);
1023
1024emit_dictionary(G, N, [_X|Xs], C, Fd) ->
1025    emit_dictionary(G, N, Xs, C, Fd);
1026
1027emit_dictionary(_G, _N, [], C, _Fd) ->
1028    C.
1029
1030
1031
1032emit_invoke(G, N, X, Fd) ->
1033
1034    {_, ArgNames, TypeList} = extract_info(G, N, X),
1035    {R, ParamTypes, _} = TypeList,
1036    OpName = ic_forms:get_java_id(X),
1037    RT = ic_java_type:getParamType(G,N,R,ret),
1038    PL = ic_util:mk_list(gen_cb_arg_list(ArgNames)),
1039    OutParamNr = count_server_send(ArgNames),
1040
1041    case count_server_receive(ArgNames) of
1042	0 ->
1043	    ok;
1044	_C ->
1045	    ic_codegen:emit(Fd, "          // Preparing input\n"),
1046	    ic_codegen:emit(Fd, "          ~sOtpInputStream __is = __env.getIs();\n",
1047			    [?ERLANGPACKAGE]),
1048	    emit_server_unmarshal_loop(G, N, X, ParamTypes, ArgNames, 1, Fd)
1049    end,
1050
1051    ic_codegen:emit(Fd, "          // Calling implementation function\n"),
1052    case RT of
1053	"void" ->
1054	    ic_codegen:emit(Fd, "          this.~s(~s);\n\n",
1055			    [OpName,PL]);
1056	_ ->
1057	    ic_codegen:emit(Fd, "          ~s _result = this.~s(~s);\n\n",
1058			    [RT, OpName, PL])
1059    end,
1060
1061    case ic_forms:is_oneway(X) of
1062	true ->
1063	    ok;
1064	false ->
1065	    ic_codegen:emit(Fd, "          // Marshaling output\n"),
1066	    ic_codegen:emit(Fd, "          ~sOtpErlangRef __ref = __env.getSref();\n",[?ERLANGPACKAGE]),
1067
1068	    case RT of
1069		"void" ->
1070		    case OutParamNr > 0 of
1071			true ->
1072			    ic_codegen:emit(Fd, "          __os.write_tuple_head(2);\n"),
1073			    ic_codegen:emit(Fd, "          __os.write_ref(__ref.node(),__ref.ids(),__ref.creation());  // Call reference\n"),
1074			    ic_codegen:emit(Fd, "          __os.write_tuple_head(~p);\n",[OutParamNr+1]),
1075			    ic_codegen:emit(Fd, "          __os.write_atom(\"ok\");\n"),
1076			    emit_server_marshal_loop(G, N, X, ParamTypes,ArgNames,1,Fd);
1077			false ->
1078			    ic_codegen:emit(Fd, "          __os.write_tuple_head(2);\n"),
1079			    ic_codegen:emit(Fd, "          __os.write_ref(__ref.node(),__ref.ids(),__ref.creation());  // Call reference\n"),
1080			    ic_codegen:emit(Fd, "          __os.write_atom(\"ok\");\n\n")
1081		    end;
1082		_ ->
1083		    case OutParamNr > 0 of
1084			true ->
1085			    ic_codegen:emit(Fd, "          __os.write_tuple_head(2);\n"),
1086			    ic_codegen:emit(Fd, "          __os.write_ref(__ref.node(),__ref.ids(),__ref.creation());  // Call reference\n"),
1087			    ic_codegen:emit(Fd, "          __os.write_tuple_head(~p);\n",[OutParamNr+1]),
1088
1089			    case ic_java_type:isBasicType(G,N,R) of
1090				true ->
1091				    ic_codegen:emit(Fd, "          __os~s(_result);  // Return value\n",
1092						    [ic_java_type:marshalFun(G,N,X,R)]);
1093				false ->
1094				    ic_codegen:emit(Fd, "          ~s(__os,_result);  // Return value\n",
1095						    [ic_java_type:marshalFun(G,N,X,R)])
1096			    end,
1097			    emit_server_marshal_loop(G, N, X, ParamTypes,ArgNames,1,Fd);
1098			false ->
1099			    ic_codegen:emit(Fd, "          __os.write_tuple_head(2);\n"),
1100			    ic_codegen:emit(Fd, "          __os.write_ref(__ref.node(),__ref.ids(),__ref.creation());  // Call reference\n"),
1101
1102			    case ic_java_type:isBasicType(G,N,R) of
1103				true ->
1104				    ic_codegen:emit(Fd, "          __os~s(_result);  // Return value\n\n",
1105						    [ic_java_type:marshalFun(G,N,X,R)]);
1106				false ->
1107				    ic_codegen:emit(Fd, "          ~s(__os,_result);  // Return value\n\n",
1108						    [ic_java_type:marshalFun(G,N,X,R)])
1109			    end
1110		    end
1111	    end,
1112	    ic_codegen:nl(Fd)
1113    end.
1114
1115
1116emit_server_unmarshal_loop(_,_,_,_,[],_,Fd) ->
1117    ic_codegen:nl(Fd);
1118emit_server_unmarshal_loop(G, N, X, [Type|Types], [{in, Arg}|Args], Counter, Fd) ->
1119    case ic_java_type:isBasicType(G,N,Type) of
1120	true ->
1121	    ic_codegen:emit(Fd, "          ~s ~s = __is~s;  // In value\n",
1122			    [ic_java_type:getType(G,N,Type),
1123			     Arg,
1124			     ic_java_type:unMarshalFun(G,N,X,Type)]);
1125	false ->
1126	    ic_codegen:emit(Fd, "          ~s ~s = ~s.unmarshal(__is);  // In value\n",
1127			    [ic_java_type:getType(G,N,Type),
1128			     Arg,
1129			     ic_java_type:getUnmarshalType(G,N,X,Type)])
1130    end,
1131    emit_server_unmarshal_loop(G, N, X, Types, Args, Counter+1, Fd);
1132emit_server_unmarshal_loop(G, N, X, [Type|Types],[{inout, Arg}|Args], Counter, Fd) ->
1133    Holder = ic_java_type:getHolderType(G,N,Type),
1134    case ic_java_type:isBasicType(G,N,Type) of
1135	true ->
1136%	    OtpEncVar = ic_java_type:getUnmarshalType(G,N,X,Type),
1137	    ic_codegen:emit(Fd, "          ~s _~s = __is~s;\n",
1138			    [ic_java_type:getType(G,N,Type),
1139			     Arg,
1140			     ic_java_type:unMarshalFun(G,N,X,Type)]),
1141	    ic_codegen:emit(Fd, "          ~s ~s = new ~s(_~s);  // InOut value\n",
1142			    [Holder,
1143			     Arg,
1144			     Holder,
1145			     Arg]);
1146	false ->
1147	    ic_codegen:emit(Fd, "          ~s ~s = new ~s();  // InOut value\n",
1148			    [Holder,
1149			     Arg,
1150			     Holder]),
1151	    ic_codegen:emit(Fd, "          ~s._unmarshal(__is);\n",
1152			    [Arg])
1153    end,
1154    emit_server_unmarshal_loop(G, N, X, Types, Args, Counter+1, Fd);
1155emit_server_unmarshal_loop(G, N, X, [Type|Types],[{out, Arg}|Args], Counter, Fd) ->
1156    Holder = ic_java_type:getHolderType(G,N,Type),
1157    ic_codegen:emit(Fd, "          ~s ~s = new ~s();  // Out value\n", [Holder, Arg, Holder]),
1158    emit_server_unmarshal_loop(G, N, X, Types, Args, Counter, Fd).
1159
1160
1161emit_server_marshal_loop(_,_,_,_,[],_,_Fd) ->
1162    ok;
1163emit_server_marshal_loop(G, N, X, [_Type|Types],[{in, _Arg}|Args], Counter, Fd) ->
1164    emit_server_marshal_loop(G, N, X, Types, Args, Counter, Fd);
1165emit_server_marshal_loop(G, N, X, [Type|Types],[{_, Arg}|Args], Counter, Fd) ->
1166%    Holder = ic_java_type:getHolderType(G,N,Type),
1167    case ic_java_type:isBasicType(G,N,Type) of
1168	true ->
1169	    ic_codegen:emit(Fd, "          __os~s(~s.value);  // Out/InOut value\n",
1170			    [ic_java_type:marshalFun(G,N,X,Type),Arg]);
1171	false ->
1172	    ic_codegen:emit(Fd, "          ~s._marshal(__os);  // Out/InOut value\n",
1173			    [Arg])
1174    end,
1175    emit_server_marshal_loop(G, N, X, Types, Args, Counter+1, Fd).
1176
1177
1178
1179
1180
1181%%%----------------------------------------------------
1182%%%
1183%%%   Utilities
1184%%%
1185%%%----------------------------------------------------
1186
1187extract_info(_G, N, X) when is_record(X, op) ->
1188    Name	=  ic_util:to_undersc([ic_forms:get_id2(X) | N]),
1189    Args	= X#op.params,
1190    ArgNames	= mk_c_vars(Args),
1191    TypeList	= {ic_forms:get_type(X),
1192		   lists:map(fun(Y) -> ic_forms:get_type(Y) end, Args),
1193		   []
1194		  },
1195    {Name, ArgNames, TypeList};
1196extract_info(_G, N, X) ->
1197    Name	=  ic_util:to_undersc([ic_forms:get_id2(X) | N]),
1198    {Name, [], []}.
1199
1200%% Input is a list of parameters (in parse form) and output is a list
1201%% of parameter attribute and variable names.
1202mk_c_vars(Params) ->
1203    lists:map(fun(P) -> {A, _} = P#param.inout,
1204			{A, ic_forms:get_id(P#param.id)}
1205	      end,
1206	      Params).
1207
1208%%
1209handle_preproc(G, _N, line_nr, X) ->
1210    Id = ic_forms:get_java_id(X),
1211    Flags = X#preproc.aux,
1212    case Flags of
1213	[] -> ic_genobj:push_file(G, Id);
1214	_ ->
1215	    lists:foldr(fun({_, _, "1"}, Gprim) -> ic_genobj:push_file(Gprim, Id);
1216			   ({_, _, "2"}, Gprim) -> ic_genobj:pop_file(Gprim, Id);
1217			   ({_, _, "3"}, Gprim) -> ic_genobj:sys_file(Gprim, Id) end,
1218			G, Flags)
1219    end;
1220handle_preproc(G, _N, _Other, _X) ->
1221    G.
1222
1223
1224%%
1225gen_par_list(_, _, _, [], []) ->
1226    [];
1227gen_par_list(G, N, X, [Type |Types], [{Attr, Arg}|Args]) ->
1228    JType = ic_java_type:getParamType(G, N, Type, Attr),
1229    [JType ++ " " ++ Arg |
1230     gen_par_list(G, N, X, Types, Args)].
1231
1232
1233gen_marshal_par_list(_, _, _, [], []) ->
1234    [];
1235gen_marshal_par_list(G, N, X, [_Type |Types], [{out, _Arg}|Args]) ->
1236    gen_marshal_par_list(G, N, X, Types, Args);
1237gen_marshal_par_list(G, N, X, [Type |Types], [{Attr, Arg}|Args]) ->
1238    JType = ic_java_type:getParamType(G, N, Type, Attr),
1239    [JType ++ " " ++ Arg |
1240     gen_marshal_par_list(G, N, X, Types, Args)].
1241
1242
1243gen_unmarshal_par_list(_, _, _, [], []) ->
1244    [];
1245gen_unmarshal_par_list(G, N, X, [_Type |Types], [{in, _Arg}|Args]) ->
1246    gen_unmarshal_par_list(G, N, X, Types, Args);
1247gen_unmarshal_par_list(G, N, X, [Type |Types], [{Attr, Arg}|Args]) ->
1248    JType = ic_java_type:getParamType(G, N, Type, Attr),
1249    [JType ++ " " ++ Arg |
1250     gen_unmarshal_par_list(G, N, X, Types, Args)].
1251
1252
1253%%
1254gen_client_marshal_call_par_list([]) ->
1255    [];
1256gen_client_marshal_call_par_list([{out, _Arg}|Args]) ->
1257    gen_client_marshal_call_par_list(Args);
1258gen_client_marshal_call_par_list([{_Attr, Arg}|Args]) ->
1259    [Arg | gen_client_marshal_call_par_list(Args)].
1260
1261
1262gen_client_unmarshal_call_par_list([]) ->
1263    [];
1264gen_client_unmarshal_call_par_list([{in, _Arg}|Args]) ->
1265    gen_client_unmarshal_call_par_list(Args);
1266gen_client_unmarshal_call_par_list([{_Attr, Arg}|Args]) ->
1267    [Arg | gen_client_unmarshal_call_par_list(Args)].
1268
1269
1270
1271count_client_receive(ArgNames) ->
1272    count_client_receive(ArgNames,0).
1273
1274count_client_receive([],C) ->
1275    C;
1276count_client_receive([{in, _Arg}|Args],C) ->
1277    count_client_receive(Args,C);
1278count_client_receive([_|Args],C) ->
1279    count_client_receive(Args,C+1).
1280
1281
1282
1283count_client_send(ArgNames) ->
1284    count_client_send(ArgNames,0).
1285
1286count_client_send([],C) ->
1287    C;
1288count_client_send([{out, _Arg}|Args],C) ->
1289    count_client_send(Args,C);
1290count_client_send([_|Args],C) ->
1291    count_client_send(Args,C+1).
1292
1293
1294gen_cb_arg_list([]) ->
1295    [];
1296gen_cb_arg_list([{_Attr, Arg}|Args]) ->
1297    [Arg | gen_cb_arg_list(Args)].
1298
1299
1300count_server_receive(ArgNames) ->
1301    count_server_receive(ArgNames,0).
1302
1303count_server_receive([],C) ->
1304    C;
1305count_server_receive([_|Args],C) ->
1306    count_server_receive(Args,C+1).
1307
1308
1309count_server_send(ArgNames) ->
1310    count_server_send(ArgNames,0).
1311
1312count_server_send([],C) ->
1313    C;
1314count_server_send([{in, _Arg}|Args],C) ->
1315    count_server_send(Args,C);
1316count_server_send([_|Args],C) ->
1317    count_server_send(Args,C+1).
1318
1319
1320
1321
1322
1323%%%-------------------------------------------------------
1324
1325
1326emit_type_function(G, N, X, Fd) ->
1327
1328    TC = ic_forms:get_type_code(G, N, X),
1329
1330    %%io:format("X = ~p\nTC = ~p\n",[X,TC]),
1331
1332    ic_codegen:emit(Fd, "   private static ~sTypeCode _tc;\n",[?ICPACKAGE]),
1333    ic_codegen:emit(Fd, "   synchronized public static ~sTypeCode type() {\n\n",[?ICPACKAGE]),
1334
1335    ic_codegen:emit(Fd, "     if (_tc != null)\n"),
1336    ic_codegen:emit(Fd, "       return _tc;\n\n"),
1337
1338    emit_type_function(TC, 0, Fd),
1339
1340    ic_codegen:emit(Fd, "\n     _tc = _tc0;\n"),
1341
1342    ic_codegen:emit(Fd, "\n     return _tc0;\n"),
1343    ic_codegen:emit(Fd, "   }\n\n").
1344
1345
1346
1347emit_type_function({tk_struct, ID, Name, ML}, C, Fd) -> %% struct
1348    ic_codegen:emit(Fd, "     ~sTypeCode _tc~p =\n",[?ICPACKAGE,C]),
1349    ic_codegen:emit(Fd, "       new ~sTypeCode();\n", [?ICPACKAGE]),
1350    ic_codegen:emit(Fd, "     _tc~p.kind(~sTCKind.tk_struct);\n", [C,?ICPACKAGE]),
1351    ic_codegen:emit(Fd, "     _tc~p.id(~p);\n", [C,ID]),
1352    ic_codegen:emit(Fd, "     _tc~p.name(~p);\n", [C,Name]),
1353    ic_codegen:emit(Fd, "     _tc~p.member_count(~p);\n", [C,length(ML)]),
1354    emit_struct_members(ML, C, C+1, 0, Fd);
1355
1356emit_type_function({tk_enum, ID, Name, MNames}, C, Fd) -> %% enum
1357    ic_codegen:emit(Fd, "     ~sTypeCode _tc~p =\n",[?ICPACKAGE,C]),
1358    ic_codegen:emit(Fd, "       new ~sTypeCode();\n", [?ICPACKAGE]),
1359    ic_codegen:emit(Fd, "     _tc~p.kind(~sTCKind.tk_enum);\n", [C,?ICPACKAGE]),
1360    ic_codegen:emit(Fd, "     _tc~p.id(~p);\n", [C,ID]),
1361    ic_codegen:emit(Fd, "     _tc~p.name(~p);\n", [C,Name]),
1362    ic_codegen:emit(Fd, "     _tc~p.member_count(~p);\n", [C,length(MNames)]),
1363    emit_enum_members(MNames, C, 0, Fd),
1364    C+1;
1365
1366emit_type_function({tk_array, ET, L}, C, Fd) -> %% array
1367    ic_codegen:emit(Fd, "     ~sTypeCode _tc~p =\n",[?ICPACKAGE,C]),
1368    ic_codegen:emit(Fd, "       new ~sTypeCode();\n", [?ICPACKAGE]),
1369    ic_codegen:emit(Fd, "     _tc~p.kind(~sTCKind.tk_array);\n", [C,?ICPACKAGE]),
1370    ic_codegen:emit(Fd, "     _tc~p.id(id());\n",[C]),
1371    ic_codegen:emit(Fd, "     _tc~p.length(~p);\n", [C,L]),
1372    C1 = C+1,
1373    C2 = emit_type_function(ET, C1, Fd),
1374    ic_codegen:emit(Fd, "     _tc~p.content_type(_tc~p);\n", [C,C1]),
1375    C2;
1376
1377emit_type_function({tk_sequence, ET, L}, C, Fd) -> %% sequence
1378    ic_codegen:emit(Fd, "     ~sTypeCode _tc~p =\n",[?ICPACKAGE,C]),
1379    ic_codegen:emit(Fd, "       new ~sTypeCode();\n", [?ICPACKAGE]),
1380    ic_codegen:emit(Fd, "     _tc~p.kind(~sTCKind.tk_sequence);\n", [C,?ICPACKAGE]),
1381    ic_codegen:emit(Fd, "     _tc~p.id(id());\n",[C]),
1382    ic_codegen:emit(Fd, "     _tc~p.length(~p);\n", [C,L]),
1383    C1 = C+1,
1384    C2 = emit_type_function(ET, C1, Fd),
1385    ic_codegen:emit(Fd, "     _tc~p.content_type(_tc~p);\n", [C,C1]),
1386    C2;
1387
1388emit_type_function({tk_string, L}, C, Fd) -> %% string
1389    ic_codegen:emit(Fd, "     ~sTypeCode _tc~p =\n",[?ICPACKAGE,C]),
1390    ic_codegen:emit(Fd, "       new ~sTypeCode();\n", [?ICPACKAGE]),
1391    ic_codegen:emit(Fd, "     _tc~p.kind(~sTCKind.tk_string);\n", [C,?ICPACKAGE]),
1392    ic_codegen:emit(Fd, "     _tc~p.length(~p);\n", [C,L]),
1393    C+1;
1394
1395emit_type_function({tk_union, ID, Name, DT, DI, LL}, C, Fd) -> %% union
1396
1397    ic_codegen:emit(Fd, "     ~sTypeCode _tc~p =\n",[?ICPACKAGE,C]),
1398    ic_codegen:emit(Fd, "       new ~sTypeCode();\n", [?ICPACKAGE]),
1399    ic_codegen:emit(Fd, "     _tc~p.kind(~sTCKind.tk_union);\n", [C,?ICPACKAGE]),
1400    ic_codegen:emit(Fd, "     _tc~p.id(~p);\n", [C,ID]),
1401    ic_codegen:emit(Fd, "     _tc~p.name(~p);\n", [C,Name]),
1402
1403    C1 = C+1,
1404    C2 = emit_type_function(DT, C1, Fd),
1405
1406    ic_codegen:emit(Fd, "     _tc~p.discriminator_type(_tc~p);\n", [C,C1]),
1407    ic_codegen:emit(Fd, "     _tc~p.default_index(~p);\n", [C,DI]),
1408    ic_codegen:emit(Fd, "     _tc~p.member_count(~p);\n", [C,length(LL)]),
1409
1410    emit_union_labels(LL, C, DT, C2, 0, Fd);
1411
1412emit_type_function(tk_term, C, Fd) -> %% term, must change it to tk_any
1413    ic_codegen:emit(Fd, "     ~sTypeCode _tc~p =\n",[?ICPACKAGE,C]),
1414    ic_codegen:emit(Fd, "       new ~sTypeCode();\n", [?ICPACKAGE]),
1415    ic_codegen:emit(Fd, "     _tc~p.kind(~sTCKind.tk_any);\n", [C,?ICPACKAGE]),
1416    C+1;
1417
1418emit_type_function(TC, C, Fd) -> %% other
1419    ic_codegen:emit(Fd, "     ~sTypeCode _tc~p =\n",[?ICPACKAGE,C]),
1420    ic_codegen:emit(Fd, "       new ~sTypeCode();\n", [?ICPACKAGE]),
1421    ic_codegen:emit(Fd, "     _tc~p.kind(~sTCKind.~p);\n", [C,?ICPACKAGE,TC]),
1422    C+1.
1423
1424
1425
1426emit_struct_members([], _, TCtr, _, _Fd) ->
1427    TCtr;
1428emit_struct_members([{Name,MT}|Rest], BTCtr, TCtr, I, Fd) ->
1429    ic_codegen:emit(Fd, "     _tc~p.member_name(~p,~p);\n", [BTCtr,I,Name]),
1430    TCtr2 = emit_type_function(MT, TCtr, Fd),
1431    ic_codegen:emit(Fd, "     _tc~p.member_type(~p,_tc~p);\n", [BTCtr,I,TCtr]),
1432    emit_struct_members(Rest, BTCtr, TCtr2, I+1, Fd).
1433
1434emit_enum_members([], _, _, _Fd) ->
1435    ok;
1436emit_enum_members([Name|Names], BTCtr, I, Fd) ->
1437    ic_codegen:emit(Fd, "     _tc~p.member_name(~p,~p);\n", [BTCtr,I,Name]),
1438    emit_enum_members(Names, BTCtr, I+1, Fd).
1439
1440
1441emit_union_labels([], _, _, TCtr, _, _) ->
1442    TCtr;
1443emit_union_labels([{L, LN, LT}|Rest], BTCtr, DT, TCtr, I, Fd) ->
1444    ic_codegen:emit(Fd, "     ~sAny _any~p =\n",[?ICPACKAGE,TCtr]),
1445    ic_codegen:emit(Fd, "       new ~sAny();\n", [?ICPACKAGE]),
1446    TCtr1 = TCtr+1,
1447    TCtr2 = emit_type_function(LT, TCtr1,Fd),
1448    ic_codegen:emit(Fd, "     _any~p.type(_tc~p);\n",[TCtr,TCtr1]),
1449
1450    case L of
1451	default ->
1452	    ic_codegen:emit(Fd, "     _any~p.insert_atom(\"default\");\n", [TCtr]);
1453	_ ->
1454	    case DT of
1455		tk_boolean ->
1456		    ic_codegen:emit(Fd, "     _any~p.insert_boolean(~p);\n",[TCtr,L]);
1457		tk_char ->
1458		    Default = if is_integer(L) ->
1459				      [L];
1460				 true ->
1461				      L
1462			      end,
1463		    ic_codegen:emit(Fd, "     _any~p.insert_char('~s');\n",[TCtr,Default]);
1464		tk_ushort ->
1465		    ic_codegen:emit(Fd, "     _any~p.insert_ushort(~p);\n",[TCtr,L]);
1466		tk_ulong ->
1467		    ic_codegen:emit(Fd, "     _any~p.insert_ulong(~p);\n",[TCtr,L]);
1468		tk_short ->
1469		    ic_codegen:emit(Fd, "     _any~p.insert_short(~p);\n",[TCtr,L]);
1470		tk_long ->
1471		    ic_codegen:emit(Fd, "     _any~p.insert_long(~p);\n",[TCtr,L]);
1472		_ ->
1473		    ic_codegen:emit(Fd, "     _any~p.insert_string(~p);\n", [TCtr,L])
1474	    end
1475    end,
1476    ic_codegen:emit(Fd, "     _tc~p.member_label(~p,_any~p);\n", [BTCtr,I,TCtr]),
1477    ic_codegen:emit(Fd, "     _tc~p.member_name(~p,~p);\n", [BTCtr,I,LN]),
1478    TCtr3 = emit_type_function(LT, TCtr2, Fd),
1479    ic_codegen:emit(Fd, "     _tc~p.member_type(~p,_tc~p);\n", [BTCtr,I,TCtr2]),
1480    emit_union_labels(Rest, BTCtr, DT, TCtr3, I+1, Fd).
1481
1482
1483
1484
1485
1486
1487
1488
1489