1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 1998-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_code).
23
24
25-include_lib("ic/src/ic.hrl").
26-include_lib("ic/src/icforms.hrl").
27
28%%-----------------------------------------------------------------
29%% External exports
30%%-----------------------------------------------------------------
31-export([get_basetype/2, insert_typedef/3, codeDirective/2]).
32-export([gen_includes/3, gen_includes/4, mk_list/1]).
33
34-export([type_expand_op/4, type_expand_handle_op/4]).
35-export([ type_expand_op_exec/4, type_expand_all/6, type_expand/7]).
36
37-export([type_expand_null/3, type_expand_void/3, type_expand_float/3, type_expand_double/3]).
38-export([type_expand_short/3, type_expand_ushort/3, type_expand_long/3, type_expand_ulong/3]).
39-export([type_expand_longlong/3, type_expand_ulonglong/3]).
40-export([type_expand_char/3, type_expand_wchar/3, type_expand_boolean/3]).
41-export([type_expand_octet/3, type_expand_any/3,  type_expand_wstring/3]).
42-export([type_expand_object/3, type_expand_string/3, type_expand_struct/7, type_expand_union/7]).
43-export([type_expand_enum/4, type_expand_sequence/7, type_expand_array/7, type_expand_error/3]).
44
45-export([type_expand_struct_rule/3, type_expand_union_rule/2, type_expand_enum_rule/4]).
46-export([type_expand_enum_elements/3, type_expand_longdouble/3, type_expand_typecode/3]).
47-export([type_expand_principal/3, type_expand_exception/7]).
48
49%%-----------------------------------------------------------------
50%% External functions
51%%-----------------------------------------------------------------
52
53%%-------------------------------------------------------------------------------------
54%%
55%% Trackrecording of generated sequence type structs, thist is just used for C today.
56%%
57%%-------------------------------------------------------------------------------------
58
59get_basetype(G, MyId) ->
60    case ?lookup(ic_genobj:typedeftab(G), MyId) of
61	[] ->
62	     MyId;
63	X ->
64	    get_basetype(G, X)
65    end.
66
67insert_typedef(_G, "erlang_term", _) ->
68    ok;
69insert_typedef(G, MyId, DefinedAsId) ->
70    ?insert(ic_genobj:typedeftab(G), MyId, DefinedAsId).
71
72codeDirective(G,X) ->
73    case produceCode(X) of
74        true ->
75            case ic_options:get_opt(G, be) of
76                c_genserv ->
77                    c;
78		c_client ->
79		    c;
80		c_server ->
81		    c_server;
82                _ ->
83                    erlang
84            end;
85        false ->
86            case ic_options:get_opt(G, be) of
87                c_genserv ->
88                    c_no_stub;
89		c_client ->
90		    c_no_stub;
91		c_server ->
92		    c_server_no_stub;
93                _ ->
94                    erlang_no_stub
95            end
96    end.
97
98%% Checks if X should produce code
99produceCode(X) when is_record(X, module) ->
100    case ic_forms:get_body(X) of
101        [] ->
102            true;
103        List ->
104            produceModuleCode(List)
105    end;
106produceCode(_X) ->
107    false.
108
109produceModuleCode([]) ->
110    false;
111produceModuleCode([X|_Xs]) when is_record(X, const) ->
112    true;
113produceModuleCode([_X|Xs]) ->
114    produceModuleCode(Xs).
115
116%% Includes needed c file headers for included idl files
117gen_includes(Fd,G,Type) ->
118    case Type of
119	c_client ->
120	    IncludeList =
121		ic_pragma:get_included_c_headers(G),
122	    gen_includes_loop(Fd,IncludeList,Type);
123	c_server ->
124	    IncludeList =
125		ic_pragma:get_included_c_headers(G),
126	    gen_includes_loop(Fd,IncludeList,Type);
127	_ ->
128	    ok
129    end,
130    ic_codegen:nl(Fd),
131    ic_codegen:emit(Fd, "#ifdef __cplusplus\n"),
132    ic_codegen:emit(Fd, "extern \"C\" {\n"),
133    ic_codegen:emit(Fd, "#endif\n\n").
134
135
136%% Includes needed c file headers for local interfaces
137gen_includes(Fd,G,X,Type) ->
138    case Type of
139	c_client ->
140	    IncludeList =
141		ic_pragma:get_local_c_headers(G,X),
142	    gen_includes_loop(Fd,IncludeList,Type);
143	c_server ->
144	    IncludeList =
145		ic_pragma:get_local_c_headers(G,X),
146	    gen_includes_loop(Fd,IncludeList,Type);
147	_ ->
148	    ok
149    end,
150    ic_codegen:nl(Fd),
151    ic_codegen:emit(Fd, "#ifdef __cplusplus\n"),
152    ic_codegen:emit(Fd, "extern \"C\" {\n"),
153    ic_codegen:emit(Fd, "#endif\n\n").
154
155
156gen_includes_loop(_,[],_) ->
157    ok;
158gen_includes_loop(Fd,[I|Is],Type) ->
159    L = string:tokens(I,"/"),
160    File = lists:last(L),
161    case File of
162	"erlang" -> % Erlang is NOT generated that way !
163	    gen_includes_loop(Fd,Is,Type);
164	"oe_erlang" -> % Erlang is NOT generated that way !
165	    gen_includes_loop(Fd,Is,Type);
166	_ ->
167	    case Type of
168		c_client ->
169		    ic_codegen:emit(Fd, "#include \"~s.h\"\n", [File]);
170		c_server ->
171		    ic_codegen:emit(Fd, "#include \"~s__s.h\"\n", [File])
172	    end,
173	    gen_includes_loop(Fd,Is,Type)
174    end.
175
176
177
178
179%%
180%% Used in NOC only
181%%
182
183
184%%
185%% Type expand on function head comments
186%%
187type_expand_op(G,N,X,Fd) ->
188    case catch type_expand_op_exec(G,N,X,Fd) of
189	{'EXIT',_Reason} ->
190	    ic_codegen:nl(Fd),
191	    ic_codegen:emit(Fd,"%% Error under type expansion, does not affect generated code.~n",[]),
192	    ic_codegen:emit(Fd,"%%------------------------------------------------------------~n",[]);
193	_ ->
194	    ic_codegen:emit(Fd,"%%------------------------------------------------------------~n",[])
195    end.
196
197
198type_expand_op_exec(G,N,X,Fd) ->
199    InArgs = ic:filter_params([in,inout], X#op.params),
200    OutArgs = ic:filter_params([out,inout], X#op.params),
201    ParamNr = length(InArgs)+1,
202    Tabs = "",
203
204    ic_codegen:nl(Fd),
205    ic_codegen:emit(Fd,"%%------------------------------------------------------------~n",[]),
206
207     case ic_forms:is_oneway(X) of
208	false ->
209	    ic_codegen:emit(Fd,"%% Operation: ~s/~p~n",[ic_forms:get_id2(X),ParamNr]);
210	true ->
211	    ic_codegen:emit(Fd,"%% Operation: ~s/~p  (oneway)~n",[ic_forms:get_id2(X),ParamNr])
212    end,
213
214    if  X#op.raises == [] -> [];
215	true ->
216	    ic_codegen:emit(Fd,"%%~n",[]),
217	    RaisesList=["%% Raises: " ++
218			mk_list(lists:map(fun(E) -> ic_util:to_colon(E) end,
219					  X#op.raises))],
220	    ic_codegen:emit(Fd,RaisesList,[]),
221	    ic_codegen:nl(Fd)
222    end,
223
224    %% Print argument names
225    ic_codegen:emit(Fd,"%%\n",[]),
226    InArgNames = ["OE_Ref"]++[ic_util:mk_var(ic_forms:get_id(InArg#param.id)) || InArg <- InArgs ],
227    OutArgNames = ["Ret"]++[ic_util:mk_var(ic_forms:get_id(OutArg#param.id)) || OutArg <- OutArgs ],
228    case length(InArgNames) > 1 of
229	true ->
230	    ic_codegen:emit(Fd,"%% Input value(s)  : ~s~n",[mk_list(InArgNames)]);
231	false ->
232	    ic_codegen:emit(Fd,"%% Input value     : ~s~n",[mk_list(InArgNames)])
233    end,
234    case length(OutArgNames) > 1 of
235	true ->
236	    ic_codegen:emit(Fd,"%% Return value(s) : ~s~n",[mk_list(OutArgNames)]);
237	false ->
238	    ic_codegen:emit(Fd,"%% Return value    : ~s~n",[mk_list(OutArgNames)])
239    end,
240    ic_codegen:emit(Fd,"%%\n",[]),
241
242    InArgsTypeList =
243	[{ic_util:mk_var(ic_forms:get_id(InArg#param.id)),ic_forms:get_tk(InArg)} || InArg <- InArgs ],
244    case InArgsTypeList of
245	[] -> %% no input parameters
246	    ok;
247	_ ->
248	    ic_codegen:emit(Fd,"%%                                             --input-params-~n",[]),
249	    type_expand_all(G,N,X,Fd,Tabs,InArgsTypeList)
250    end,
251
252    ReturnTypeList =[{"Ret",X#op.tk}],
253    ic_codegen:emit(Fd,"%%                                             --return-value-~n",[]),
254    type_expand_all(G,N,X,Fd,Tabs,ReturnTypeList),
255
256    OutArgsTypeList =
257	[{ic_util:mk_var(ic_forms:get_id(OutArg#param.id)),ic_forms:get_tk(OutArg)} || OutArg <- OutArgs ],
258    case OutArgsTypeList of
259	[] -> %% no input parameters
260	    ok;
261	_ ->
262	    ic_codegen:emit(Fd,"%%                                             -output-values-~n",[]),
263	    type_expand_all(G,N,X,Fd,Tabs,OutArgsTypeList)
264    end.
265
266
267
268
269type_expand_handle_op(G,N,X,Fd) ->
270    case catch type_expand_handle_op_exec(G,N,X,Fd) of
271	{'EXIT',_Reason} ->
272	    ic_codegen:nl(Fd),
273	    ic_codegen:emit(Fd,"%% Error under type expansion, does not affect generated code.~n",[]),
274	    ic_codegen:emit(Fd,"%%------------------------------------------------------------~n",[]);
275	_ ->
276	    ic_codegen:emit(Fd,"%%------------------------------------------------------------~n",[])
277    end.
278
279
280type_expand_handle_op_exec(_G,_N,X,Fd) ->
281    InArgs = ic:filter_params([in,inout], X#op.params),
282    ParamNr = length(InArgs)+1,
283
284    ic_codegen:nl(Fd),
285    ic_codegen:emit(Fd,"%%------------------------------------------------------------~n",[]),
286
287    case ic_forms:is_oneway(X) of
288	false ->
289	    ic_codegen:emit(Fd,"%% Handle operation: handle_call/3~n",[]);
290	true ->
291	    ic_codegen:emit(Fd,"%% Handle operation: handle_cast/3~n",[])
292    end,
293    ic_codegen:emit(Fd,"%%~n",[]),
294    ic_codegen:emit(Fd,"%% Used for operation ~s/~p implementation~n",[ic_forms:get_id2(X),ParamNr]).
295
296
297
298type_expand_all(_G,_N,_X,_Fd,_Tabs,[]) ->
299    ok;
300type_expand_all(G,N,X,Fd,Tabs,[{ArgName,Type}|Rest]) ->
301    type_expand(G,N,X,Fd,Tabs,ArgName,Type),
302    type_expand_all(G,N,X,Fd,Tabs,Rest);
303type_expand_all(G,N,X,Fd,Tabs,[{default,_ArgName,Type}|Rest]) ->
304    type_expand(G,N,X,Fd,Tabs,"Def",Type),
305    type_expand_all(G,N,X,Fd,Tabs,Rest);
306type_expand_all(G,N,X,Fd,Tabs,[{LabelNr,_ArgName,Type}|Rest]) when is_integer(LabelNr) ->
307    type_expand(G,N,X,Fd,Tabs,"V" ++ integer_to_list(LabelNr),Type),
308    type_expand_all(G,N,X,Fd,Tabs,Rest);
309type_expand_all(G,N,X,Fd,Tabs,[{Label,_ArgName,Type}|Rest]) ->
310    type_expand(G,N,X,Fd,Tabs,Label,Type),
311    type_expand_all(G,N,X,Fd,Tabs,Rest).
312
313
314
315type_expand(_G,_N,_X,Fd,Tabs,Name,tk_null) ->
316    type_expand_null(Fd,Tabs,Name);
317type_expand(_G,_N,_X,Fd,Tabs,Name,tk_void) ->
318    type_expand_void(Fd,Tabs,Name);
319type_expand(_G,_N,_X,Fd,Tabs,Name,tk_float) ->
320    type_expand_float(Fd,Tabs,Name);
321type_expand(_G,_N,_X,Fd,Tabs,Name,tk_double) ->
322    type_expand_double(Fd,Tabs,Name);
323type_expand(_G,_N,_X,Fd,Tabs,Name,tk_longdouble) ->
324    type_expand_longdouble(Fd,Tabs,Name);
325type_expand(_G,_N,_X,Fd,Tabs,Name,tk_short) ->
326    type_expand_short(Fd,Tabs,Name);
327type_expand(_G,_N,_X,Fd,Tabs,Name,tk_ushort) ->
328    type_expand_ushort(Fd,Tabs,Name);
329type_expand(_G,_N,_X,Fd,Tabs,Name,tk_long) ->
330    type_expand_long(Fd,Tabs,Name);
331type_expand(_G,_N,_X,Fd,Tabs,Name,tk_longlong) ->
332    type_expand_longlong(Fd,Tabs,Name);
333type_expand(_G,_N,_X,Fd,Tabs,Name,tk_ulong) ->
334    type_expand_ulong(Fd,Tabs,Name);
335type_expand(_G,_N,_X,Fd,Tabs,Name,tk_ulonglong) ->
336    type_expand_ulonglong(Fd,Tabs,Name);
337type_expand(_G,_N,_X,Fd,Tabs,Name,tk_char) ->
338    type_expand_char(Fd,Tabs,Name);
339type_expand(_G,_N,_X,Fd,Tabs,Name,tk_wchar) ->
340    type_expand_wchar(Fd,Tabs,Name);
341type_expand(_G,_N,_X,Fd,Tabs,Name,tk_boolean) ->
342    type_expand_boolean(Fd,Tabs,Name);
343type_expand(_G,_N,_X,Fd,Tabs,Name,tk_octet) ->
344    type_expand_octet(Fd,Tabs,Name);
345type_expand(_G,_N,_X,Fd,Tabs,Name,tk_any) ->
346    type_expand_any(Fd,Tabs,Name);
347type_expand(_G,_N,_X,Fd,Tabs,Name,tk_TypeCode) ->
348    type_expand_typecode(Fd,Tabs,Name);
349type_expand(_G,_N,_X,Fd,Tabs,Name,tk_Principal) ->
350    type_expand_principal(Fd,Tabs,Name);
351type_expand(G, N, X,Fd,Tabs,Name, {tk_except, Id, ExcName, ElementList}) ->
352    type_expand_exception(G, N, X, Fd,Tabs,Name,
353			  {tk_except, Id, ExcName, ElementList});
354type_expand(_G,_N,_X,Fd,Tabs,Name,{tk_fixed, _Digits, _Scale}) ->
355    type_expand_fixed(Fd,Tabs,Name);
356type_expand(_G,_N,_X,Fd,Tabs,Name,{tk_objref, _IFRId, _ObjTabs, _ObjName}) ->
357    type_expand_object(Fd,Tabs,Name);
358type_expand(_G,_N,_X,Fd,Tabs,Name,{tk_objref, _IFRId, _ObjName}) ->
359    type_expand_object(Fd,Tabs,Name);
360type_expand(_G,_N,_X,Fd,Tabs,Name,{tk_string, _Length}) ->
361    type_expand_string(Fd,Tabs,Name);
362type_expand(_G,_N,_X,Fd,Tabs,Name,{tk_wstring, _Length}) ->
363    type_expand_wstring(Fd,Tabs,Name);
364type_expand(G,N,X,Fd,Tabs,Name,{tk_union, IFRId, UnionName, DTC, DNr, LblList}) ->
365    type_expand_union(G,N,X,Fd,Tabs,Name,{tk_union, IFRId, UnionName, DTC, DNr, LblList});
366type_expand(_G,_N,_X,Fd,Tabs,Name,{tk_enum, IFRId, EnumName, ElemNameList}) ->
367    type_expand_enum(Fd,Tabs,Name,{tk_enum, IFRId, EnumName, ElemNameList});
368type_expand(G,N,X,Fd,Tabs,Name,{tk_sequence, ElemTC, Length}) ->
369    type_expand_sequence(G,N,X,Fd,Tabs,Name,{tk_sequence, ElemTC, Length});
370type_expand(G,N,X,Fd,Tabs,Name,{tk_array, ElemTC, Length}) ->
371    type_expand_array(G,N,X,Fd,Tabs,Name,{tk_array, ElemTC, Length});
372type_expand(G,N,X,Fd,Tabs,Name,{tk_struct, IFRId, StructName, TcList}) ->
373    type_expand_struct(G,N,X,Fd,Tabs,Name,{tk_struct, IFRId, StructName, TcList});
374type_expand(_G,_N,_X,Fd,Tabs,Name,_) ->
375    type_expand_error(Fd,Tabs,Name).
376
377
378%% Basic OMG IDL types
379
380type_expand_null(Fd,Tabs,Name) ->
381    ic_codegen:emit(Fd,"%%~s ~s = null()~n",[Tabs,Name]).
382
383type_expand_void(Fd,Tabs,Name) ->
384    ic_codegen:emit(Fd,"%%~s ~s = void()~n",[Tabs,Name]).
385
386type_expand_float(Fd,Tabs,Name) ->
387    ic_codegen:emit(Fd,"%%~s ~s = float()~n",[Tabs,Name]).
388
389type_expand_double(Fd,Tabs,Name) ->
390    ic_codegen:emit(Fd,"%%~s ~s = double()~n",[Tabs,Name]).
391
392type_expand_longdouble(Fd,Tabs,Name) ->
393    ic_codegen:emit(Fd,"%%~s ~s = long_double()~n",[Tabs,Name]).
394
395type_expand_short(Fd,Tabs,Name) ->
396    ic_codegen:emit(Fd,"%%~s ~s = short()~n",[Tabs,Name]).
397
398type_expand_ushort(Fd,Tabs,Name) ->
399    ic_codegen:emit(Fd,"%%~s ~s = unsigned_Short()~n",[Tabs,Name]).
400
401type_expand_long(Fd,Tabs,Name) ->
402    ic_codegen:emit(Fd,"%%~s ~s = long()~n",[Tabs,Name]).
403
404type_expand_longlong(Fd,Tabs,Name) ->
405    ic_codegen:emit(Fd,"%%~s ~s = long_Long()~n",[Tabs,Name]).
406
407type_expand_ulong(Fd,Tabs,Name) ->
408    ic_codegen:emit(Fd,"%%~s ~s = unsigned_Long()~n",[Tabs,Name]).
409
410type_expand_ulonglong(Fd,Tabs,Name) ->
411    ic_codegen:emit(Fd,"%%~s ~s = unsigned_Long_Long()~n",[Tabs,Name]).
412
413type_expand_char(Fd,Tabs,Name) ->
414    ic_codegen:emit(Fd,"%%~s ~s = char()~n",[Tabs,Name]).
415
416type_expand_wchar(Fd,Tabs,Name) ->
417    ic_codegen:emit(Fd,"%%~s ~s = wchar()~n",[Tabs,Name]).
418
419type_expand_boolean(Fd,Tabs,Name) ->
420    ic_codegen:emit(Fd,"%%~s ~s = boolean()~n",[Tabs,Name]).
421
422type_expand_octet(Fd,Tabs,Name) ->
423    ic_codegen:emit(Fd,"%%~s ~s = octet()~n",[Tabs,Name]).
424
425type_expand_any(Fd,Tabs,Name) ->
426    ic_codegen:emit(Fd,"%%~s ~s = any()~n",[Tabs,Name]).
427
428type_expand_typecode(Fd,Tabs,Name) ->
429    ic_codegen:emit(Fd,"%%~s ~s = TypeCode()~n",[Tabs,Name]).
430
431type_expand_principal(Fd,Tabs,Name) ->
432    ic_codegen:emit(Fd,"%%~s ~s = principal()~n",[Tabs,Name]).
433
434
435type_expand_fixed(Fd,Tabs,Name) ->
436    ic_codegen:emit(Fd,"%%~s ~s = fixed()~n",[Tabs,Name]).
437
438type_expand_object(Fd,Tabs,Name) ->
439    ic_codegen:emit(Fd,"%%~s ~s = Object_Ref()~n",[Tabs,Name]).
440
441
442%% Constructed OMG IDL types
443
444type_expand_string(Fd,Tabs,Name) ->
445    ic_codegen:emit(Fd,"%%~s ~s = String()~n",[Tabs,Name]).
446
447type_expand_wstring(Fd,Tabs,Name) ->
448    ic_codegen:emit(Fd,"%%~s ~s = WString()~n",[Tabs,Name]).
449
450type_expand_exception(G, N, X, Fd, Tabs, Name, {tk_except, Id, ExcName, ElementList}) ->
451    ScopedStructName = getScopedName(G, N, ExcName, Id),
452    ic_codegen:emit(Fd,"%%~s ~s = ",[Tabs, Name]),
453    type_expand_exception_rule(Fd, ScopedStructName, ElementList),
454    type_expand_all(G, N, X, Fd, Tabs, ElementList).
455
456type_expand_struct(G,N,X,Fd,Tabs,Name,{tk_struct, IFRId, StructName, TcList}) ->
457    ScopedStructName = getScopedName(G,N,StructName,IFRId),
458    ic_codegen:emit(Fd,"%%~s ~s = ",[Tabs,Name]),
459    type_expand_struct_rule(Fd,ScopedStructName,TcList),
460    type_expand_all(G,N,X,Fd,Tabs,TcList).
461
462type_expand_union(G,N,X,Fd,Tabs,Name,{tk_union, IFRId, UnionName, DTC, _DNr, LblList}) ->
463    ScopedUnionName = getScopedName(G,N,UnionName,IFRId),
464    ic_codegen:emit(Fd,"%%~s ~s = #'~s'{label, value}\n",[Tabs,Name,ScopedUnionName]),
465    type_expand(G,N,X,Fd,Tabs,"label",DTC),
466    ic_codegen:emit(Fd,"%%~s value = ",[Tabs]),
467    type_expand_union_rule(Fd,LblList),
468    type_expand_all(G,N,X,Fd,Tabs,LblList).
469
470type_expand_enum(Fd,Tabs,Name,{tk_enum, _IFRId, EnumName, ElemNameList}) ->
471    ic_codegen:emit(Fd,"%%~s ~s = ~s~n",[Tabs,Name,EnumName]),
472    type_expand_enum_rule(Fd,Tabs,EnumName,ElemNameList).
473
474type_expand_sequence(G,N,X,Fd,Tabs,Name,{tk_sequence, ElemTC, _Length}) ->
475    ic_codegen:emit(Fd,"%%~s ~s = [ ~sElem ]~n",[Tabs,Name,Name]),
476    type_expand(G,N,X,Fd,Tabs,Name++"Elem",ElemTC).
477
478type_expand_array(G,N,X,Fd,Tabs,Name,{tk_array, ElemTC, _Length}) ->
479    ic_codegen:emit(Fd,"%%~s ~s = { ~sElem[,..~sElem] }~n",[Tabs,Name,Name,Name]),
480    type_expand(G,N,X,Fd,Tabs,Name++"Elem",ElemTC).
481
482type_expand_error(Fd,Tabs,Name) ->
483    ic_codegen:emit(Fd,"%%~s ~s = ????~n",[Tabs,Name]).
484
485
486type_expand_exception_rule(Fd,_Name,[]) ->
487    ic_codegen:emit(Fd," ???? ");
488type_expand_exception_rule(Fd,Name,TcList) ->
489    ic_codegen:emit(Fd,"#'~s'{",[Name]),
490    type_expand_exception_rule(Fd,TcList).
491
492type_expand_exception_rule(Fd,[{Name,_TC}]) ->
493    ic_codegen:emit(Fd,"~s}~n",[Name]);
494type_expand_exception_rule(Fd,[{Name,_TC}|Rest]) ->
495    ic_codegen:emit(Fd,"~s,",[Name]),
496    type_expand_exception_rule(Fd,Rest).
497
498type_expand_struct_rule(Fd,_Name,[]) ->
499    ic_codegen:emit(Fd," ???? ");
500type_expand_struct_rule(Fd,Name,TcList) ->
501    ic_codegen:emit(Fd,"#'~s'{",[Name]),
502    type_expand_struct_rule(Fd,TcList).
503
504type_expand_struct_rule(Fd,[{Name,_TC}]) ->
505    ic_codegen:emit(Fd,"~s}~n",[Name]);
506type_expand_struct_rule(Fd,[{Name,_TC}|Rest]) ->
507    ic_codegen:emit(Fd,"~s,",[Name]),
508    type_expand_struct_rule(Fd,Rest).
509
510
511type_expand_union_rule(Fd,[]) ->
512    ic_codegen:emit(Fd," ????");
513type_expand_union_rule(Fd,[{default,_Name,_TC}]) ->
514    ic_codegen:emit(Fd,"Def~n",[]);
515type_expand_union_rule(Fd,[{LNr,_Name,_TC}]) when is_integer(LNr)->
516    ic_codegen:emit(Fd,"V~p~n",[LNr]);
517type_expand_union_rule(Fd,[{Label,_Name,_TC}]) ->
518    ic_codegen:emit(Fd,"~s~n",[Label]);
519type_expand_union_rule(Fd,[{default,_Name,_TC}|Rest]) ->
520    ic_codegen:emit(Fd,"Default | "),
521    type_expand_union_rule(Fd,Rest);
522type_expand_union_rule(Fd,[{LNr,_Name,_TC}|Rest]) when is_integer(LNr) ->
523    ic_codegen:emit(Fd,"V~p | ",[LNr]),
524    type_expand_union_rule(Fd,Rest);
525type_expand_union_rule(Fd,[{Label,_Name,_TC}|Rest]) ->
526    ic_codegen:emit(Fd,"~s | ",[Label]),
527    type_expand_union_rule(Fd,Rest).
528
529
530type_expand_enum_rule(Fd,Tabs,Name,[]) ->
531    ic_codegen:emit(Fd,"%%~s ~s = ????",[Tabs,Name]);
532type_expand_enum_rule(Fd,Tabs,Name,ElList) ->
533    ic_codegen:emit(Fd,"%%~s ~s = ",[Tabs,Name]),
534    type_expand_enum_rule(Fd,ElList).
535
536type_expand_enum_rule(Fd,[ElName]) ->
537    ic_codegen:emit(Fd,"'~s' ~n",[ElName]);
538type_expand_enum_rule(Fd,[First|Rest]) ->
539    ic_codegen:emit(Fd,"'~s' | ",[First]),
540    type_expand_enum_rule(Fd,Rest).
541
542type_expand_enum_elements(_Fd,_Tabs,[]) ->
543    ok;
544type_expand_enum_elements(Fd,Tabs,[Elem|Elems]) ->
545    ic_codegen:emit(Fd,"%%~s ~s = Atom()~n",[Tabs,Elem]),
546    type_expand_enum_elements(Fd,Tabs,Elems).
547
548
549
550%% Returns the right scoped name to be used
551%% along with the expansion comments
552getScopedName(G,N,Name,IfrId) ->
553    PTab = ic_genobj:pragmatab(G),
554    case ets:match(PTab,{alias,'$0',IfrId}) of
555	[] -> %% No Alias - should never happen
556	    ic_util:to_undersc(ic_pragma:mk_scope(IfrId));
557	[[[_S|N]]] -> %% An alias
558	    ic_util:to_undersc([Name|N]);
559	[[[S|FoundScope]]] -> %% Maybe inherited
560	    case ic_pragma:is_inherited_by(FoundScope,N,PTab) of
561		false -> %% Not inherited
562		    ic_util:to_undersc([S|FoundScope]);
563		true -> %% inherited
564		    ic_util:to_undersc([Name|N])
565	    end
566    end.
567
568
569%% mk_list produces a nice comma separated
570%% string of variable names
571mk_list([]) -> [];
572mk_list([Arg | Args]) ->
573    Arg ++ mk_list2(Args).
574mk_list2([Arg | Args]) ->
575    ", " ++ Arg ++ mk_list2(Args);
576mk_list2([]) -> [].
577
578
579
580%%-----------------------------------------------------------------
581%% Internal functions
582%%-----------------------------------------------------------------
583
584
585
586