1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1998-2020. 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 "ic_erlang_term*" -> 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