PageRenderTime 19ms CodeModel.GetById 10ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 1ms

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