PageRenderTime 27ms CodeModel.GetById 17ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

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

http://github.com/tybor/Liberty
Specman e | 355 lines | 292 code | 37 blank | 26 comment | 39 complexity | 6758ca8db3a6928ad55c6fc996c8e842 MD5 | raw file
  1class WRAPPERS_GENERATOR
  2   -- An application that processes the output of gccxml to produce low-level
  3   -- wrappers for functions, structures and enumerationsi and unions.
  4   -- Function having argument structures passed by value are not handled.
  5
  6insert
  7   ARGUMENTS
  8   FILE_TOOLS
  9   SHARED_SETTINGS
 10   SHARED_COLLECTIONS
 11   NAME_CONVERTER
 12   LIBERTY_VERSION
 13
 14create {ANY}
 15   make
 16
 17feature {ANY}
 18   liberty_authors: STRING "P.REDAELLI"
 19   liberty_dates: STRING "2008-2016"
 20
 21   make
 22      do
 23         log(once "wrappers generator%N")
 24         process_arguments
 25         log(once "Loading XML file: ")
 26         create tree.make(input.url)
 27         log(once "done.%N")
 28         open_plugin_files
 29         if file_exists(avoided) and then is_file(avoided) then
 30            log(once "Reading list of avoided symbols from '#(1)'.%N" # avoided)
 31            tree.read_avoided_from(avoided)
 32         end
 33
 34         if file_exists(moved) and then is_file(moved) then
 35            log(once "Reading symbols to be moved/renamed from '#(1)'.%N" # moved)
 36            tree.read_moved_from(moved)
 37         end
 38
 39         if file_exists(flags) and then is_file(flags) then
 40            log(once "Reading enumerations that will be forcefully wrapped as flags from '#(1)'.%N" # flags)
 41            tree.read_flags_from(flags)
 42         end
 43
 44         if file_exists(descriptions) and then is_file(descriptions) then
 45            log(once "Reading descriptions flags from '#(1)'.%N" # descriptions)
 46            tree.read_descriptions_from(descriptions)
 47         end
 48
 49         log(once "Making wrappers.%N")
 50         tree.emit_wrappers
 51         -- tree.namespaces.for_each(agent {GCCXML_NODE}.emit_wrappers)
 52         close_plugin_files
 53      end
 54
 55   tree: GCCXML_TREE
 56
 57   input: INPUT_STREAM
 58
 59   path: POSIX_PATH_NAME
 60
 61   preprocessor_label: STRING
 62
 63   avoided: STRING
 64
 65   renamed: STRING
 66
 67   moved: STRING
 68
 69   flags: STRING
 70
 71   descriptions: STRING
 72
 73   process_arguments
 74         -- Process arguments. If some argument is not understood `print_usage' is invoked and the program exits.
 75         --| TODO: Why isn't this using COMMAND_LINE_TOOLS? --djk
 76      local
 77         arg, gccxml_prefix, standard_typedefs: STRING; i: INTEGER
 78      do
 79         check
 80            global = False
 81            verbose = False
 82         end
 83         -- Setting defaults
 84         flags := once "flags"
 85         descriptions := once "descriptions"
 86         avoided := once "avoided"
 87         renamed := once "renamed"
 88         moved := once "moved"
 89         standard_typedefs := once "STANDARD_C_LIBRARY_TYPES"
 90
 91         if argument_count = 0 then
 92            print_usage
 93            die_with_code(exit_success_code)
 94         else
 95            from
 96               i := 1
 97            until
 98               i > argument_count
 99            loop
100               arg := argument(i)
101               if arg.has_prefix(once "--") then
102                  arg.remove_first
103               end
104               if arg.is_equal(once "-local") then
105                  settings.set_global(False)
106               elseif arg.is_equal(once "-global") then
107                  settings.set_global(True)
108               elseif arg.is_equal(once "-emit-standard-typedefs") then
109                  settings.use_standard_typedefs
110               elseif arg.is_equal(once "-apply-patches") then
111                  not_yet_implemented
112               elseif arg.is_equal(once "-descriptions") then
113                  i := i + 1
114                  if i <= argument_count then
115                     descriptions := argument(i)
116                  else
117                     std_error.put_line(once "No description file given.")
118                     print_usage
119                  end
120               elseif arg.is_equal(once "-standard-typedefs") then
121                  i := i + 1
122                  if i <= argument_count then
123                     if is_valid_class_name(argument(i)) then
124                        standard_typedefs := eiffel_class_name(argument(i), Void)
125                     else
126                        std_error.put_line(once "#(1)  not a valid class name" # argument(i))
127                     end
128                  else
129                     std_error.put_line(once "Name of class containing standard typedefs not given")
130                     print_usage
131                  end
132               elseif arg.is_equal(once "-flags") then
133                  i := i + 1
134                  if i <= argument_count then
135                     flags := argument(i)
136                  else
137                     std_error.put_line(once "No flags file given")
138                     print_usage
139                  end
140               elseif arg.is_equal(once "-avoided") then
141                  i := i + 1
142                  if i <= argument_count then
143                     avoided := argument(i)
144                  else
145                     std_error.put_line(once "No avoided file given")
146                     print_usage
147                  end
148               elseif arg.is_equal(once "-moved") then
149                  not_yet_implemented
150                  i := i + 1
151                  if i <= argument_count then
152                     moved := argument(i)
153                  else
154                     std_error.put_line(once "No moved functions file given")
155                     print_usage
156                  end
157               elseif arg.is_equal(once "-version") or else arg.is_equal(once "-v") then
158                  print_version
159                  die_with_code(0)
160               elseif arg.is_equal(once "-help") or else arg.is_equal(once "-h") then
161                  print_usage
162                  die_with_code(0)
163               elseif arg.is_equal(once "-verbose") then
164                  settings.set_verbose(True)
165                  -- TODO: re-enable grouping output on standard output
166                  -- elseif arg.is_equal(once "-on-standard-output") then
167                  --    settings.set_directory(Void)
168               else
169                  if file_exists(arg) then
170                     -- Current arg should be the XML file. The following
171                     -- are headers to process.
172                     create path.make_from_string(arg)
173                     create {TEXT_FILE_READ} input.connect_to(arg)
174                     from
175                        i := i + 1
176                     until
177                        i > argument_count
178                     loop
179                        headers.add(argument(i))
180                        i := i + 1
181                     end
182                  else
183                     std_error.put_string(once "Input file does not exist: ")
184                     std_error.put_line(arg)
185                     print_usage
186                  end
187               end
188
189               i := i + 1
190            end
191            if input = Void then
192               log(once "Using standard input. Prefix will be the basename of the current directory.")
193               create path.make_current
194               input := std_input
195            end
196
197            gccxml_prefix := path.last.twin
198            gccxml_prefix.remove_tail(path.extension.count)
199            settings.set_typedefs(eiffel_class_name(gccxml_prefix, "_TYPES"))
200            settings.set_standard_typedefs(standard_typedefs)
201            preprocessor_label := eiffel_class_name(gccxml_prefix, "_LIBERTY_PLUGIN")
202
203            if verbose then
204               if global then
205                  std_error.put_line(once "Generation wrappers for all the C features found.")
206               else
207                  std_error.put_string(once "Generating low-level wrappers only for ")
208                  std_error.put_integer(headers.count)
209                  std_error.put_string(once " files: ")
210                  headers.for_each(agent (a_string: ABSTRACT_STRING)
211                     do
212                        std_error.put_string(once "'")
213                        std_error.put_string(a_string)
214                        std_error.put_string(once "', ")
215                     end(?))
216                  std_error.put_new_line
217               end
218            end
219         end
220      end
221
222   open_plugin_files
223      local
224         cwd, plugin: DIRECTORY; file: FILE; bd: BASIC_DIRECTORY
225      do
226         create cwd.scan_current_working_directory
227         if not cwd.has_file(once "plugin") then
228            if not bd.create_new_directory(once "plugin") then
229               log("Couldn't create plugin directory")
230               die_with_code(exit_failure_code)
231            end
232         end
233
234         file := cwd.file("plugin")
235         if not file.is_directory then
236            log("%'plugin'  not a directory")
237            die_with_code(exit_failure_code)
238         end
239
240         plugin := file.as_directory
241         if not plugin.has_file(once "c") then
242            if not bd.create_new_directory(once "plugin/c") then
243               log("Couldn't create plugin/c directory")
244               die_with_code(exit_failure_code)
245            end
246         end
247
248         file := plugin.file(once "c")
249         if not file.is_directory then
250            log("%'plugin/c'  not a directory")
251            die_with_code(exit_failure_code)
252         end
253         -- TODO: check that both pdirectory exists.
254         include.connect_to(once "plugin/c/plugin.h")
255         include.put_string(automatically_generated_c_file)
256         source.connect_to(once "plugin/c/plugin.c")
257         source.put_string(automatically_generated_c_file)
258         --source.put_string("#include %"plugin.h%"")
259         source.put_line("#ifndef " + preprocessor_label + "%N%
260         %#   define " + preprocessor_label)
261      ensure
262         include.is_connected
263         source.is_connected
264      end
265
266   close_plugin_files
267      do
268         source.put_line("#endif")
269         source.disconnect
270         include.disconnect
271      end
272
273   print_usage
274      do
275         std_error.put_line(once "[
276            Usage: wrappers-generator [--verbose|-v] [--local] [--global] [--directory dir] output.gcc-xml filenames...
277
278            Option summary:
279
280            Information:
281              -h -help            Display this help information
282              -V -version         Display Liberty Eiffel version information
283              -v -verbose         Display detailed information about what the program is
284                                   doing
285
286            C features selection:
287              -local              Produce functions, structures and enumeration classes
288                                   only for the given files. Otherwise all the necessary
289                                   files will be created. This is the default. Only the
290                                   last global and local flag will be considered.
291              -global             Emits wrappers for every feature found in the XML file.
292                                   For usual wrappers it is normally not needed. Only the
293                                   last global and local flag will be considered.
294
295            Enumerations as flags:
296              -flags <file>       Read a list of enumerations that will be forcefully
297                                   wrapped as a flag. In fact sometimes there is no way to
298                                   distinguish when an enumeration is used as-it-is or to
299                                   contain flags. If this option is not given the program
300                                   will use the "flags" file if present.
301
302            Eiffel header comments:
303              -descriptions <file>
304                                  Apply the descriptions found in <file>. Each line
305                                   contains the description of a class or of a class'
306                                   feature. The syntax for a class description is
307                                   `CLASS description', for a feature description
308                                   `CLASS.feature description'. Trailing and leading
309                                   spaces are trimmed from each line. If this option is
310                                   not given the program will use the "descriptions" file
311                                   if present.
312
313            Typedefs:
314              -standard-typedefs <CLASS_NAME>
315                                  Use <CLASS_NAME> as the class containing the wrappers
316                                  for defined typedefs. If not given the default
317                                  "STANDARD_C_LIBRARY_TYPES" will be used.
318              -emit-standard-typedefs
319                                  Emit dummy queries useful for anchored declarations
320                                   (i.e. "like long") for C types that can have different
321                                   sizes on different architectures and for the typedefs
322                                   defined in the C99 standard.  If this flag is not given
323                                   the class containing the defined typedefs will insert
324                                   the CLASS_NAME defined with "-standard-typedefs"
325                                   option.
326
327            Symbol selection:
328              -moved <file>       Read from <file> a list of functions with the Liberty
329                                   class they wrapped in; sometimes function declarations
330                                   aren't made in a public header but in hidden places,
331                                   i.e. memcpy. If this option is not given the program
332                                   will use the "moved" file if present.
333              -avoided <file>     Do not wrap the symbols found in <file>. If this option
334                                   is not given the program will use the "avoided" file if
335                                   present.
336
337            The basename of the provided XML file made by gccxml will be used as prefix
338            for the typedef class and preprocessor symbol.
339         ]")
340         die_with_code(exit_success_code)
341      end
342
343end -- class WRAPPERS_GENERATOR
344-- class WRAPPER_GENERATOR
345-- Copyright (C) 2008-2017: Paolo Redaelli
346-- wrappers-generator  is free software: you can redistribute it and/or modify it
347-- under the terms of the GNU General Public License as publhed by the Free
348-- Software Foundation, either version 2 of the License, or (at your option)
349-- any later version.
350-- wrappers-generator is distributed in the hope that it will be useful, but
351-- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
352-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
353-- more details.
354-- You should have received a copy of the GNU General Public License along with
355-- th program.  If not, see <http://www.gnu.org/licenses/>.