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

http://github.com/tybor/Liberty · Specman e · 268 lines · 214 code · 16 blank · 38 comment · 8 complexity · 4cba812e43f67bbac7d8fba2fd183d2c MD5 · raw file

  1. class GCCXML_TREE
  2. -- A partially validated representation of an XML file made by gccxml
  3. -- Effective heirs will emit wrappers using the plugin machanm.
  4. inherit
  5. XML_TREE
  6. redefine make, new_node, open_node
  7. end
  8. insert
  9. DESCRIPTIONS
  10. SHARED_COLLECTIONS
  11. SHARED_SETTINGS
  12. EXCEPTIONS
  13. FILE_TOOLS
  14. create {ANY}
  15. make
  16. feature {ANY}
  17. make (url: URL)
  18. do
  19. create moved.make
  20. Precursor(url)
  21. end
  22. new_node (node_name: UNICODE_STRING; line, column: INTEGER): XML_COMPOSITE_NODE
  23. do
  24. inspect
  25. node_name.as_utf8
  26. when "Argument" then
  27. create {C_ARGUMENT} Result.make(node_name, line, column)
  28. when "ArrayType" then
  29. create {C_ARRAY_TYPE} Result.make(node_name, line, column)
  30. when "Base" then
  31. create {CPP_BASE_NODE} Result.make(node_name, line, column)
  32. when "Class" then
  33. create {CPP_CLASS} Result.make(node_name, line, column)
  34. when "Constructor" then
  35. create {C_CONSTRUCTOR} Result.make(node_name, line, column)
  36. when "Converter" then
  37. create {CONVERTER_NODE} Result.make(node_name, line, column)
  38. when "CvQualifiedType" then
  39. create {C_QUALIFIED_TYPE} Result.make(node_name, line, column)
  40. when "Destructor" then
  41. create {DESTRUCTOR_NODE} Result.make(node_name, line, column)
  42. when "Ellipsis" then
  43. create {C_ELLIPSIS} Result.make(node_name, line, column)
  44. when "Enumeration" then
  45. create {C_ENUM} Result.make(node_name, line, column)
  46. when "EnumValue" then
  47. create {C_ENUM_VALUE} Result.make(node_name, line, column)
  48. when "Field" then
  49. create {C_FIELD} Result.make(node_name, line, column)
  50. when "File" then
  51. create {C_FILE} Result.make(node_name, line, column)
  52. when "Function" then
  53. create {C_FUNCTION} Result.make(node_name, line, column)
  54. when "FunctionType" then
  55. create {C_FUNCTION_TYPE} Result.make(node_name, line, column)
  56. when "FundamentalType" then
  57. create {C_FUNDAMENTAL_TYPE} Result.make(node_name, line, column)
  58. when "GCC_XML" then
  59. create {GCC_XML} Result.make(node_name, line, column)
  60. when "Method" then
  61. create {METHOD_NODE} Result.make(node_name, line, column)
  62. when "MethodType" then
  63. create {METHOD_TYPE_NODE} Result.make(node_name, line, column)
  64. when "Namespace" then
  65. create {C_NAMESPACE} Result.make(node_name, line, column)
  66. when "NamespaceAlias" then
  67. create {C_NAMESPACE_ALIAS} Result.make(node_name, line, column)
  68. when "OffsetType" then
  69. create {OFFSET_TYPE_NODE} Result.make(node_name, line, column)
  70. when "OperatorFunction" then
  71. create {OPERATOR_FUNCTION_NODE} Result.make(node_name, line, column)
  72. when "OperatorMethod" then
  73. create {OPERATOR_METHOD_NODE} Result.make(node_name, line, column)
  74. when "PointerType" then
  75. create {C_POINTER_TYPE} Result.make(node_name, line, column)
  76. when "ReferenceType" then
  77. create {C_REFERENCE_TYPE} Result.make(node_name, line, column)
  78. when "Struct" then
  79. create {C_STRUCT_NODE} Result.make(node_name, line, column)
  80. when "Typedef" then
  81. create {C_TYPEDEF} Result.make(node_name, line, column)
  82. when "Union" then
  83. create {C_UNION} Result.make(node_name, line, column)
  84. when "Unimplemented" then
  85. create {UNIMPLEMENTED_NODE} Result.make(node_name, line, column)
  86. when "Variable" then
  87. create {C_VARIABLE} Result.make(node_name, line, column)
  88. else
  89. raise(node_name.as_utf8 + " does not have an GCCXML_NODE")
  90. -- create {XML_COMPOSITE_NODE} Result.make(node_name, line, column)
  91. end
  92. -- TODO: it would be nice to allow direct inspection of UNICODE_STRING
  93. -- and other COMPARABLE classes
  94. end
  95. open_node (node_name: UNICODE_STRING; line, column: INTEGER)
  96. local
  97. storable: STORABLE_NODE
  98. do
  99. Precursor(node_name, line, column)
  100. storable ?= open_nodes.top
  101. if storable /= Void then
  102. storable.store
  103. end
  104. end
  105. feature {ANY} -- Wrappers emittions
  106. emit_wrappers
  107. local
  108. node: GCCXML_NODE
  109. do
  110. log(once "Moving symbols.%N")
  111. moved.for_each(agent move_symbol(?,?))
  112. log(once "Making typedefs and assigning names to typedeffed types.%N")
  113. typedefs.emit_wrappers
  114. -- Assign each field to the composed node it belongs to
  115. -- Wrap namespaces as Eiffel clusters which are directories containing classes
  116. -- Assign each function to the file they belong to.
  117. functions.for_each(agent move_feature(?))
  118. -- Assign each variable to the file they belong to.
  119. variables.for_each(agent move_feature(?))
  120. namespaces.for_each(agent {C_NAMESPACE}.emit_wrapper)
  121. check
  122. node ?:= root
  123. end
  124. -- this is not stricly necessary, we check that root is actually a GCCXML_NODE
  125. node ::= root
  126. node.emit_wrappers
  127. -- Note that an eventual assertion like "check node/=Void end" or a
  128. -- run-time check like "if node/=Void then node.emit_wrappers end"
  129. -- are not necessary since "node ::= root" actually requires root to be a GCCXML_NODE
  130. end
  131. move_feature (a_feature: WRAPPER_FEATURE)
  132. require
  133. a_feature /= Void
  134. local
  135. destination: ABSTRACT_STRING; file: C_FILE
  136. do
  137. if not a_feature.is_anonymous then
  138. destination := moved.reference_at(a_feature.c_string_name)
  139. if destination /= Void then
  140. -- user required move
  141. file := files_by_name.reference_at(destination)
  142. log(once "Moving #(1) into #(2) as requested.%N"
  143. # a_feature.c_string_name # file.c_string_name)
  144. else
  145. -- a_feature belong to the file as declared in the gcc-xml file
  146. file := files.reference_at(a_feature.c_file.id)
  147. log(once "Moving #(1) from #(2) into #(3).%N"
  148. # a_feature.c_string_name # a_feature.c_file.c_string_name # file.c_string_name)
  149. end
  150. check
  151. file /= Void
  152. end
  153. file.features.add_last(a_feature)
  154. end
  155. end
  156. feature {ANY}
  157. read_flags_from (a_file_name: STRING)
  158. -- Read the lt of enumeration that shall be wrapped as flags from the
  159. -- file named `a_file_name'.
  160. require
  161. a_file_name /= Void
  162. file_exists(a_file_name)
  163. is_file(a_file_name)
  164. do
  165. flag_enums.add_from_file(a_file_name)
  166. end
  167. read_avoided_from (a_file_name: STRING)
  168. -- Read from the file named `a_file_name' the lt of symbols that will
  169. -- be avoided, i.e. not wrapped.
  170. require
  171. a_file_name /= Void
  172. file_exists(a_file_name)
  173. is_file(a_file_name)
  174. do
  175. avoided_symbols.add_from_file(a_file_name)
  176. end
  177. moved: HASHED_DICTIONARY[ABSTRACT_STRING, ABSTRACT_STRING]
  178. read_moved_from (a_name: STRING)
  179. -- Read the file with `a_name' and fills `moved' dictionary. For each line the
  180. -- first word will be used as key, the second as value. The rest of the
  181. -- line is ignored and may be considered comment.
  182. -- Used to read the lt of renamed symbols and moved functions.
  183. require
  184. a_name /= Void
  185. file_exists(a_name)
  186. is_file(a_name)
  187. local
  188. file: TEXT_FILE_READ; symbol, value: STRING; words: STRING_INPUT_STREAM
  189. do
  190. create file.connect_to(a_name)
  191. check
  192. file.is_connected
  193. end
  194. from
  195. file.read_line
  196. until
  197. file.end_of_input
  198. loop
  199. if file.last_string.has_prefix(once "--") then
  200. -- skip the comment
  201. else
  202. create words.from_string(file.last_string)
  203. words.read_word
  204. if not words.last_string.is_empty then
  205. -- twin is used because last_string is reused. Otherwise the symbols will change once stored. And this is bad, like crossing rays.
  206. symbol := words.last_string.twin
  207. words.read_word
  208. if not words.last_string.is_empty then
  209. value := words.last_string.twin
  210. log(once "Symbol #(1) moved to #(2)%N" # symbol # value)
  211. moved.put(value, symbol)
  212. end
  213. end
  214. -- Issueing words.skip_remainder_of_line is useless
  215. end
  216. file.read_line
  217. end
  218. end
  219. move_symbol (a_file_name, a_symbol: ABSTRACT_STRING)
  220. -- Makes `a_symbol' as if it was part of file with `a_file_name'.
  221. local
  222. f: C_FILE; symbol: MOVABLE_NODE
  223. do
  224. f := files_by_name.reference_at(a_file_name)
  225. if f = Void then
  226. log(once "Symbol `#(1)' can't be considered part of file #(2): file not referenced by in input file%N" # a_symbol # a_file_name)
  227. else
  228. symbol ?= symbols.reference_at(a_symbol)
  229. if symbol /= Void then
  230. log(once "Considering #(1) as declared into file #(2)%N"
  231. # a_symbol # a_file_name)
  232. symbol.set_file(f)
  233. else
  234. log(once "Cannot find symbol #(1) (that would be considered part of #(2))%N"
  235. # a_symbol # a_file_name)
  236. end
  237. end
  238. end
  239. invariant
  240. moved /= Void
  241. end -- class GCCXML_TREE
  242. -- Copyright (C) 2008-2017: Paolo Redaelli
  243. -- wrappers-generator is free software: you can redistribute it and/or modify it
  244. -- under the terms of the GNU General Public License as publhed by the Free
  245. -- Software Foundation, either version 2 of the License, or (at your option)
  246. -- any later version.
  247. -- wrappers-generator is distributed in the hope that it will be useful, but
  248. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  249. -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  250. -- more details.
  251. -- You should have received a copy of the GNU General Public License along with
  252. -- th program. If not, see <http://www.gnu.org/licenses/>.