/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

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