PageRenderTime 6ms CodeModel.GetById 2ms app.highlight 1ms RepoModel.GetById 1ms app.codeStats 0ms

/src/tools/wrappers-generator/type_translator.e

http://github.com/tybor/Liberty
Specman e | 273 lines | 187 code | 24 blank | 62 comment | 19 complexity | c0f83f21e8f9c1edbad503cb028e309c MD5 | raw file
  1deferred class TYPE_TRANSLATOR
  2	-- Translate names of C symbols into Eiffel features
  3
  4insert
  5	SHARED_SETTINGS
  6	WRAPPER_GENERATOR_EXCEPTIONS
  7	NAME_CONVERTER
  8	EXCEPTIONS
  9
 10feature {ANY} -- Type-system translations
 11	referred_type (an_argument: XML_COMPOSITE_NODE): XML_COMPOSITE_NODE is
 12		-- The type ultimately referred by `an_argument'. Typedef are followed
 13		-- until a non-typedef type is found.  
 14	require an_argument /= Void
 15	local type: UNICODE_STRING
 16	do
 17		type := an_argument.attribute_at(once U"type")
 18		if an_argument.name.is_equal(once U"Typedef") then Result:=referred_type(types.at(type))
 19		else Result:=an_argument
 20		end
 21	end
 22 
 23	is_void (an_argument: XML_COMPOSITE_NODE): BOOLEAN is
 24		require
 25			argument_not_void: an_argument /= Void
 26		local
 27			type: UNICODE_STRING
 28		do
 29			if an_argument.name.is_equal(once U"FundamentalType") then
 30				if an_argument.attribute_at(once U"name").is_equal(U"void") then
 31					Result := True
 32				else
 33					Result := False
 34				end
 35			else
 36				type := an_argument.attribute_at(once U"type")
 37				if type = Void then
 38					Result := False
 39				else
 40					Result := is_void(types.at(type))
 41				end
 42			end
 43		end
 44
 45	eiffel_type_of_string (an_id: UNICODE_STRING): STRING is
 46			-- The Eiffel type name correspondent to the C type contained in `an_id'
 47		require
 48			an_id /= Void
 49		local
 50			a_type: XML_COMPOSITE_NODE
 51		do
 52			a_type := types.reference_at(dequalify(an_id))
 53			if a_type /= Void then
 54				Result := eiffel_type_of(a_type)
 55			end
 56		end
 57
 58	eiffel_type_of (an_argument: XML_COMPOSITE_NODE): STRING is
 59			-- The Eiffel type usable to wrap `an_argument'. If it does not
 60			-- have a proper wrapper type Result is Void and `last_error'
 61			-- describes the issue using one of the strings from
 62			-- EIFFEL_GCC_XML_EXCEPTIONS. Constructs currently not
 63			-- automatically wrappable are: "Expanded" structures (i.e. passed
 64			-- by-value and not by-reference, i.e. non using a pointer),
 65			-- unions, C++ references, complex reals (float and double) 
 66
 67			-- Typedefs are resolved using anchored declarations (i.e. "like
 68			-- gchar").
 69		require
 70			argument_not_void: an_argument /= Void
 71			no_previous_errors: last_error = Void
 72		do
 73			Result:=type_of(an_argument,anchored_typedefs)
 74		end
 75
 76	anchored_typedefs: BOOLEAN is True
 77	resolved_typedefs: BOOLEAN is False
 78
 79	type_of (an_argument: XML_COMPOSITE_NODE; are_typedefs_anchored: BOOLEAN): STRING is
 80			-- The Eiffel type usable to wrap `an_argument'. If it does not
 81			-- have a proper wrapper type Result is Void and `last_error'
 82			-- describes the issue using one of the strings from
 83			-- EIFFEL_GCC_XML_EXCEPTIONS. Constructs currently not
 84			-- automatically wrappable are: "Expanded" structures (i.e. passed
 85			-- by-value and not by-reference, i.e. non using a pointer),
 86			-- unions, C++ references, complex reals (float and double) 
 87
 88			-- If `are_typedefs_anchored' is True typedefs will be resolved
 89			-- using anchored declarations (i.e. "like gchar"); otherwise
 90			-- Result will be the ultimate fundamental type.
 91		local
 92			name: STRING; size: INTEGER
 93			uniname: UNICODE_STRING
 94			referred: XML_COMPOSITE_NODE
 95		do
 96			-- Known nodes: FundamentalType Constructor Ellipsis Typedef
 97			-- ArrayType Argument Enumeration PointerType EnumValue
 98			-- Struct GCC_XML CvQualifiedType Namespace FunctionType
 99			-- Variable File Field Function Union ReferenceType
100			inspect an_argument.name.to_utf8
101			when "FundamentalType" then
102				name := an_argument.attribute_at(once U"name").to_utf8
103				if name.is_equal(once "void") then Result := once ""
104				else
105					size := an_argument.attribute_at(once U"size").to_utf8.to_integer
106					if name.has_substring(once "char") then
107						-- check size=8 end
108						Result := once "CHARACTER"
109					elseif name.has_substring(once "complex") then
110						-- could be "complex double" "complex float",
111						-- "complex long double"
112						log("Unhandled complex type found at line @(1): @(2)%N",<<an_argument.line.out,name>>)
113						last_error := unhandled_complex_type
114					elseif name.has_substring(once "unsigned") then
115						-- check name.has_substring(once "int") end
116						if are_naturals_used then
117							inspect size
118							when 16 then Result := once "NATURAL_16"
119							when 32 then Result := once "NATURAL_32"
120							when 64 then Result := once "NATURAL_64"
121							else
122								log(once "Unknown unsigned int of sizei @(1)",<<size.out>>)
123								last_error := unhandled_unsigned_integer_type
124							end
125						else
126							inspect size
127							when 16 then Result := once "INTEGER_16"
128							when 32 then Result := once "INTEGER_32"
129							when 64 then Result := once "INTEGER_64"
130							else
131								log(once "Unknown unsigned int of size @(1)",<<size.out>>)
132								last_error := unhandled_unsigned_integer_type
133							end
134						end
135					elseif name.has_substring(once "int") then
136						inspect size
137						when 16 then Result := once "INTEGER_16"
138						when 32 then Result := once "INTEGER_32"
139						when 64 then Result := once "INTEGER_64"
140						else
141							std_error.put_line("Unknown int of size" + size.out)
142							last_error := unhandled_integer_type
143						end
144					elseif name.has_substring(once "float") then
145						-- check size=32 end
146						Result := once "REAL_32"
147					elseif name.has_substring(once "double") then
148						inspect size
149						when 32 then
150							log_string(once "What a pretty strange thing: a 32 bit double! They are usually called float.")
151							Result := once "REAL_32"
152						when 64 then Result := once "REAL_64"
153						when 80 then Result := once "REAL_80"
154						when 128 then Result := once "REAL_128"
155						else
156							log(once "Double of unhandled length @(1) using REAL_128",<<size.out>>)
157							last_error := unhandled_double_type
158						end
159					else
160						log("@(1) @(2)",<<unhandled_type, name>>)
161						last_error := unhandled_type
162					end
163				end
164			when "Typedef" then
165				if are_typedefs_anchored then
166					-- The Eiffel type of a typedef is anchored to a query
167					-- named like the C typedef. The actual type of that query
168					-- is the actual type referred by the typedef. i.e.
169					-- "typedef long int foo; f(foo a);" produce "f(an_a: like
170
171					Result := ((once "like ") + 
172					 	eiffel_feature(an_argument.attribute_at(once U"name").as_utf8))
173				else
174					uniname := dequalify(an_argument.attribute_at(once U"type"))
175					referred := types.at(uniname)
176					Result := type_of(referred,are_typedefs_anchored)
177				end
178			when "CvQualifiedType" then
179				uniname := dequalify(an_argument.attribute_at(once U"type"))	
180				check types.has(uniname) end
181				referred := types.at(uniname)
182				Result := type_of(referred,are_typedefs_anchored)
183			when "Argument", "Variable", "Field" then
184				-- The following note may be outdated:
185				-- -----------------------------------
186				-- Recursively discover the correct type: the actual type
187				-- of a typedef is the type it is referring to.
188				-- It was Result:=eiffel_type_of(types.at(dequalify(an_argument.attribute_at(once U"type"))))
189				-- but it requires that eiffel_type_of accept a Void argument
190				-- and that the types dictionary is always correctly filled.
191				uniname := dequalify(an_argument.attribute_at(once U"type"))
192				referred := types.reference_at(uniname)
193				if referred/=Void then Result := eiffel_type_of(referred)
194				else
195					name := an_argument.attribute_at(once U"name").to_utf8
196					log(once "Warning! Type Argument/Variable/Field @(1) - @(2) has no Eiffel type",
197					<<name,uniname.as_utf8>>)
198					last_error := unhandled_type
199				end
200			when "Enumeration" then Result := once "INTEGER_32"
201			when "ArrayType", "PointerType" then Result := once "POINTER"
202			when "FunctionType" then Result := once "POINTER"
203			when "Struct" then last_error := unhandled_structure_type
204			when "Function" then
205				log_string(once "C functions does not have a valid Eiffel wrapper type (a function pointer does have it).")
206				last_error := unhandled_type
207			when "Union" then last_error := unhandled_union_type
208			when "ReferenceType" then
209				std_error.put_line(once "C++ reference does not have a valid Eiffel wrapper type.")
210				last_error := unhandled_reference_type
211			else last_error := unhandled_type
212			end
213		ensure when_void_last_error_is_set: Result = Void implies last_error /= Void
214		end
215
216	has_type_error: BOOLEAN is
217			-- Is `last_error' related to types?
218		do
219			Result := last_error = unhandled_type or else last_error = unhandled_complex_type or else last_error = unhandled_unsigned_integer_type or else last_error = unhandled_integer_type or else last_error = unhandled_double_type or else last_error = unhandled_structure_type or else last_error = unhandled_union_type or else last_error = unhandled_reference_type
220		end
221
222	last_error: STRING
223			-- A description of the latest error occurred
224
225	types: HASHED_DICTIONARY[XML_COMPOSITE_NODE, UNICODE_STRING]
226			-- Types by their id
227
228	typedefs: LINKED_LIST[XML_COMPOSITE_NODE]
229
230feature {} -- Implementation:
231	deconst (a_string: UNICODE_STRING): UNICODE_STRING is
232		obsolete "Use dequalify instead"
233		do
234			Result:=dequalify(a_string)
235		end
236
237
238feature {ANY} -- Constants
239	integer_size: INTEGER is
240		-- The size of an INTEGER in bytes
241	once
242		Result := {INTEGER_32 1}.object_size // 8
243	end
244
245	real_size: INTEGER is
246		-- The sice of a REAL_64 in bytes
247	once
248		Result := {REAL_64 1.0}.object_size // 8
249	end
250	-- External types are described in
251	-- http://smarteiffel.loria.fr/wiki/en/index.php/External_types
252	-- could be obsolete.
253
254invariant
255	non_void_types: types /= Void
256	non_void_typedefs: typedefs /= Void
257
258end -- class TYPE_TRANSLATOR
259
260-- Copyright 2008,2009 Paolo Redaelli
261
262-- eiffel-gcc-xml  is free software: you can redistribute it and/or modify it
263-- under the terms of the GNU General Public License as published by the Free
264-- Software Foundation, either version 2 of the License, or (at your option)
265-- any later version.
266
267-- eiffel-gcc-xml is distributed in the hope that it will be useful, but
268-- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
269-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
270-- more details.
271
272-- You should have received a copy of the GNU General Public License along with
273-- this program.  If not, see <http://www.gnu.org/licenses/>.