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_fetch).
23
24-include("icforms.hrl").
25
26-export([member2type/3]).
27
28-export([fetchTk/3, isArray/3, isBasicType/1, isBasicType/2,
29	 isBasicType/3, isBasicTypeOrEterm/3, isEterm/3, isString/3,
30	 isStruct/3, isUnion/3, name2type/2, searchIncludedTk/2,
31	 searchInsideTks/2, searchTk/2, searchTk/3]).
32
33name2type(G, Name) ->
34    S = ic_genobj:tktab(G),
35    ScopedName = lists:reverse(string:tokens(Name,"_")),
36    InfoList = ets:lookup( S, ScopedName ),
37    filter( InfoList ).
38
39
40
41%% This is en overloaded function,
42%% differs in input on unions
43member2type(_G, X, I) when is_record(X, union)->
44    Name = ic_forms:get_id2(I),
45    case lists:keysearch(Name,2,element(6,X#union.tk)) of
46	false ->
47	    error;
48	{value,Rec} ->
49	    fetchType(element(3,Rec))
50    end;
51member2type( G, SName, MName ) ->
52
53    S = ic_genobj:tktab( G ),
54    SNList = lists:reverse(string:tokens(SName,"_")),
55    ScopedName = [MName | SNList],
56    InfoList = ets:lookup( S, ScopedName ),
57
58    case filter( InfoList ) of
59	error ->
60	    %% Try a little harder, seeking inside tktab
61	    case lookup_member_type_in_tktab(S, ScopedName, MName) of
62		error ->
63		    %% Check if this is the "return to return1" case
64		    case MName of
65			"return1" ->
66			    %% Do it all over again !
67			    ScopedName2 = ["return" | SNList],
68			    InfoList2 = ets:lookup( S, ScopedName2 ),
69			    case filter( InfoList2 ) of
70				error ->
71				    %% Last resort: seek in pragma table
72				    lookup_type_in_pragmatab(G, SName);
73
74				Other ->
75				    Other
76			    end;
77			_ ->
78			    %% Last resort: seek in pragma table
79			    lookup_type_in_pragmatab(G, SName)
80		    end;
81		Other ->
82		    Other
83	    end;
84	Other ->
85	    Other
86    end.
87
88
89lookup_member_type_in_tktab(S, ScopedName, MName) ->
90    case ets:match_object(S, {'_',member,{MName,'_'},nil}) of
91	[] ->
92	    error;
93	[{_FullScopedName,member,{MName,TKInfo},nil}]->
94	    fetchType( TKInfo );
95	List ->
96	    lookup_member_type_in_tktab(List,ScopedName)
97    end.
98
99lookup_member_type_in_tktab([],_ScopedName) ->
100    error;
101lookup_member_type_in_tktab([{FullScopedName,_,{_,TKInfo},_}|Rest],ScopedName) ->
102    case lists:reverse(string:tokens(ic_util:to_undersc(FullScopedName),"_")) of
103	ScopedName ->
104	    fetchType(TKInfo);
105	_ ->
106	    lookup_member_type_in_tktab(Rest,ScopedName)
107    end.
108
109
110lookup_type_in_pragmatab(G, SName) ->
111    S = ic_genobj:pragmatab(G),
112
113    %% Look locally first
114    case ets:match(S,{file_data_local,'_','_','$2','_','_',SName,'_','_'}) of
115	[] ->
116	    %% No match, seek included
117	    case ets:match(S,{file_data_included,'_','_','$2','_','_',SName,'_','_'}) of
118
119		[] ->
120		    error;
121		[[Type]] ->
122		    io:format("1 Found(~p) : ~p~n",[SName,Type]),
123		    Type
124	    end;
125
126	[[Type]] ->
127	    io:format("2 Found(~p) : ~p~n",[SName,Type]),
128	    Type
129    end.
130
131
132
133
134filter( [] ) ->
135    error;
136filter( [I | Is ] ) ->
137    case I of
138	{ _, member, { _, TKINFO }, _ } ->
139	    fetchType( TKINFO );
140
141        { _, struct, _, _ } ->
142	    struct;
143
144	{ _, typedef, TKINFO, _ } ->
145	    fetchType( TKINFO );
146
147	{ _, module, _, _ } ->
148	    module;
149
150	{ _, interface, _, _ } ->
151	    interface;
152
153	{ _, op, _, _ } ->
154	    op;
155
156	{ _,enum, _, _ } ->
157	    enum;
158
159	{ _, spellcheck } ->
160	    filter( Is );
161
162	_ ->
163	    error
164    end.
165
166
167fetchType( { tk_sequence, _, _ } ) ->
168    sequence;
169fetchType( { tk_array, _, _ } ) ->
170    array;
171fetchType( { tk_struct, _, _, _} ) ->
172    struct;
173fetchType( { tk_string, _} ) ->
174    string;
175fetchType( tk_short ) ->
176    short;
177fetchType( tk_long ) ->
178    long;
179fetchType( tk_ushort ) ->
180    ushort;
181fetchType( tk_ulong ) ->
182    ulong;
183fetchType( tk_float ) ->
184    float;
185fetchType( tk_double ) ->
186    double;
187fetchType( tk_boolean ) ->
188    boolean;
189fetchType( tk_char ) ->
190    char;
191fetchType( tk_octet ) ->
192    octet;
193fetchType( { tk_enum, _, _, _ } ) ->
194    enum;
195fetchType( { tk_union, _, _, _, _, _ } ) ->
196    union;
197fetchType( tk_any ) ->
198    any;
199fetchType( _ ) ->
200    error.
201
202isBasicTypeOrEterm(G, N, S) ->
203    case isBasicType(G, N, S) of
204	true ->
205	    true;
206	false ->
207	    isEterm(G, N, S)
208    end.
209
210
211isEterm(G, N, S) when element(1, S) == scoped_id ->
212    {FullScopedName, _, _TK, _} = ic_symtab:get_full_scoped_name(G, N, S),
213    case ic_code:get_basetype(G, ic_util:to_undersc(FullScopedName)) of
214	"erlang_term" ->
215	    true;
216	"ETERM*" ->
217	    true;
218	_X ->
219	    false
220    end;
221isEterm(_G, _Ni, _X) ->
222    false.
223
224isBasicType(G, N, S) when element(1, S) == scoped_id ->
225    {_, _, TK, _} = ic_symtab:get_full_scoped_name(G, N, S),
226    isBasicType(fetchType(TK));
227isBasicType(_G, _N, {string, _} ) ->
228    false;
229isBasicType(_G, _N, {Type, _} ) ->
230    isBasicType(Type).
231
232
233isBasicType(G, Name) ->
234    isBasicType(name2type(G, Name )).
235
236
237isBasicType(Type) ->
238    lists:member(Type,
239		 [tk_short,short,
240		  tk_long,long,
241		  tk_ushort,ushort,
242		  tk_ulong,ulong,
243		  tk_float,float,
244		  tk_double,double,
245		  tk_boolean,boolean,
246		  tk_char,char,
247		  tk_octet,octet]).
248
249
250
251isString(G, N, T) when element(1, T) == scoped_id ->
252    case ic_symtab:get_full_scoped_name(G, N, T) of
253	{_FullScopedName, _, {'tk_string',_}, _} ->
254	    true;
255	_ ->
256	    false
257    end;
258isString(_G, _N, T)  when is_record(T, string) ->
259    true;
260isString(_G, _N, _Other) ->
261    false.
262
263
264isArray(G, N, T) when element(1, T) == scoped_id ->
265    case ic_symtab:get_full_scoped_name(G, N, T) of
266	{_FullScopedName, _, {'tk_array', _, _}, _} ->
267	    true;
268	_ ->
269	    false
270    end;
271isArray(_G, _N, T)  when is_record(T, array) ->
272    true;
273isArray(_G, _N, _Other) ->
274    false.
275
276
277
278isStruct(G, N, T) when element(1, T) == scoped_id ->
279    case ic_symtab:get_full_scoped_name(G, N, T) of
280	{_FullScopedName, _, {'tk_struct', _, _, _}, _} ->
281	    true;
282	_ ->
283	    false
284    end;
285isStruct(_G, _N, T)  when is_record(T, struct) ->
286    true;
287isStruct(_G, _N, _Other) ->
288    false.
289
290
291
292isUnion(G, N, T) when element(1, T) == scoped_id ->
293    case ic_symtab:get_full_scoped_name(G, N, T) of
294	{_FullScopedName, _, {'tk_union', _, _, _,_,_}, _} ->
295	    true;
296	_Other ->
297	    false
298    end;
299isUnion(_G, _N, T)  when is_record(T, union) ->
300    true;
301isUnion(_G, _N, _Other) ->
302    false.
303
304
305
306%%------------------------------------------------------------
307%%
308%% Always fetchs TK of a record.
309%%
310%%------------------------------------------------------------
311fetchTk(G,N,X) ->
312    case ic_forms:get_tk(X) of
313	undefined ->
314	    searchTk(G,ictk:get_IR_ID(G, N, X));
315	TK ->
316	    TK
317    end.
318
319
320%%------------------------------------------------------------
321%%
322%% seek type code when not accessible by get_tk/1
323%%
324%%------------------------------------------------------------
325searchTk(G,IR_ID) ->
326    S = ic_genobj:tktab(G),
327    case catch searchTk(S,IR_ID,typedef) of
328	{value,TK} ->
329	    TK;
330	_ -> %% false / exit
331 	    case catch searchTk(S,IR_ID,struct) of
332		{value,TK} ->
333		    TK;
334		_  ->  %% false / exit
335		    case catch searchTk(S,IR_ID,union) of
336			{value,TK} ->
337			    TK;
338			_ ->
339			    undefined
340		    end
341	    end
342    end.
343
344
345searchTk(S,IR_ID,Type) ->
346    L = lists:flatten(ets:match(S,{'_',Type,'$1','_'})),
347    case lists:keysearch(IR_ID,2,L) of
348	{value,TK} ->
349	    {value,TK};
350	false ->
351	    searchInsideTks(L,IR_ID)
352    end.
353
354
355searchInsideTks([],_IR_ID) ->
356    false;
357searchInsideTks([{tk_array,TK,_}|Xs],IR_ID) ->
358    case searchIncludedTk(TK,IR_ID) of
359	{value,TK} ->
360	    {value,TK};
361	false ->
362	    searchInsideTks(Xs,IR_ID)
363    end.
364
365
366searchIncludedTk({tk_array,TK,_},IR_ID) ->
367    searchIncludedTk(TK,IR_ID);
368searchIncludedTk({tk_sequence,TK,_},IR_ID) ->
369    searchIncludedTk(TK,IR_ID);
370searchIncludedTk(TK,_IR_ID) when is_atom(TK) ->
371    false;
372searchIncludedTk(TK,IR_ID) ->
373    case element(2,TK) == IR_ID of
374	true ->
375	    {value,TK};
376	false ->
377	    false
378    end.
379
380
381
382
383
384
385
386
387
388
389
390