/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

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