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

http://github.com/tybor/Liberty · Specman e · 281 lines · 187 code · 19 blank · 75 comment · 11 complexity · 5ff8432f9930850e62bbca798626ad86 MD5 · raw file

  1. class C_FUNCTION
  2. -- A "Function" node of an XML file made by gccxml.
  3. inherit
  4. CONTEXTED_NODE
  5. IDENTIFIED_NODE
  6. MOVABLE_NODE
  7. -- hence a NAMED_NODE and a FILED_NODE
  8. redefine compute_eiffel_name
  9. end
  10. STORABLE_NODE
  11. WRAPPER_FEATURE
  12. redefine compute_eiffel_name
  13. end
  14. create {GCCXML_TREE}
  15. make
  16. feature {ANY}
  17. store
  18. do
  19. log("Storing function '#(1)', line #(2)%N" # c_string_name # line_row.to_utf8 )
  20. if is_anonymous then
  21. log("Skipping anonymous funtion at line #(2)%N" # line_row.as_utf8)
  22. else
  23. check
  24. c_string_name /= Void
  25. end
  26. symbols.put(Current, c_string_name)
  27. functions.add_first(Current)
  28. end
  29. end
  30. returns: UNICODE_STRING
  31. do
  32. Result := attribute_at(once U"returns")
  33. end
  34. return_type: C_TYPE
  35. do
  36. Result := types.reference_at(returns)
  37. end
  38. compute_eiffel_name
  39. do
  40. cached_eiffel_name := eiffel_feature(c_string_name)
  41. end
  42. has_arguments: BOOLEAN
  43. -- Does Current function have arguments?
  44. do
  45. inspect children_count
  46. when 0 then Result := False
  47. when 1 then Result := not argument(1).is_ellipsis
  48. else Result := True
  49. end
  50. end
  51. is_variadic: BOOLEAN
  52. -- Does current function accept a variable number of arguments?
  53. do
  54. if children_count > 0 then
  55. Result := argument(children_count).is_ellipsis
  56. else
  57. Result := False
  58. end
  59. end
  60. is_wrappable: BOOLEAN
  61. -- Are all arguments wrappable and its return type either void or
  62. -- wrappable? The variadic part of the function, the ellipsis ("...")
  63. -- is ignored.
  64. local
  65. i: INTEGER_32; a_return_type: C_TYPE
  66. do
  67. a_return_type := return_type
  68. Result := a_return_type/=Void and then (a_return_type.is_void or a_return_type.has_wrapper) -- return_type.referree.has_wrapper
  69. if Result then
  70. -- Check for
  71. from
  72. i := children_count
  73. until
  74. not Result or i < 1
  75. loop
  76. Result := argument(i).has_wrapper or else argument(i).is_ellipsis
  77. i := i - 1
  78. end
  79. end
  80. end
  81. is_to_be_emitted: BOOLEAN
  82. do
  83. Result := not avoided_symbols.has(c_string_name)
  84. end
  85. wrap_on (a_stream: OUTPUT_STREAM)
  86. do
  87. if not is_wrappable then
  88. log("Function `#(1)' is not wrappable%N" # c_string_name)
  89. buffer.reset
  90. buffer.append(once " -- unwrappable function #(1) in file `#(2)'%N" #
  91. c_string_name # c_file.c_string_name)
  92. -- TODO: provide the reason; using developer_exception_name
  93. -- triggers some recursion bug AFAIK. Paolo 2009-10-02
  94. elseif not is_public then
  95. log(once "Skipping 'hidden' function `#(1)'%N" # c_string_name)
  96. buffer.append(once "%T-- `hidden' function #(1) skipped.%N" # c_string_name)
  97. elseif not namespace.is_main then
  98. log(once "Skipping function `#(1)' belonging to namespace #(2) which is not wrapped%N" #
  99. c_string_name # namespace.c_string_name)
  100. buffer.append(once "%T-- function #(1) in unwrapped namespace #(2) skipped.%N" #
  101. c_string_name # namespace.c_string_name)
  102. elseif avoided_symbols.has(c_string_name) then
  103. log(once "Function `#(1)' is among the avoided symbols: not wrapping as requested.%N" # c_string_name)
  104. buffer.append(once "%T-- function #(1) skipped as requested.%N" # c_string_name)
  105. else
  106. log(once "Function #(1)" # c_string_name)
  107. buffer.append(once "%T#(1)" # eiffel_name)
  108. append_arguments
  109. append_return_type
  110. append_description
  111. append_body
  112. log(once "%N")
  113. end
  114. buffer.print_on(a_stream)
  115. end
  116. append_description
  117. -- Put a description on 'buffer' formatting it as an Eiffel comment
  118. -- with lines shorter that 'description_lenght' characters.
  119. -- local description: COLLECTION[STRING]; word: STRING; iter: ITERATOR[STRING]; length,new_length: INTEGER
  120. do
  121. -- TODO: complete C_FUNCTION.append_description
  122. buffer.append(once "%N%T%T-- function #(1) (in `#(2)')%N" #
  123. c_string_name # c_file.c_string_name)
  124. -- description := feature_description(class_name, name)
  125. -- if description/=Void then
  126. -- from
  127. -- iter:=a_description.get_new_iterator; iter.start;
  128. -- buffer.append(once "%N%T%T-- "); length:=0
  129. -- until iter.is_off loop
  130. -- word := iter.item
  131. -- new_length := length + word.count
  132. -- if new_length>description_lenght then
  133. -- buffer.append(once "%N%T%T-- ")
  134. -- length := 0
  135. -- else
  136. -- buffer.put(' ')
  137. -- length := new_length + 1
  138. -- end
  139. -- buffer.append(word)
  140. -- iter.next
  141. -- end
  142. -- end
  143. end
  144. append_arguments
  145. -- Append the arguments of function referred by `a_node' into
  146. -- `buffer'.
  147. -- C requires at least one argument before the eventual ellips;
  148. -- C++ allows ellips to be the only argument. (source
  149. -- http://publib.boulder.ibm.com/infocenter/iadthelp/v7r0/index.jsp?topic=/com.ibm.etools.eries.langref.doc/as400clr155.htm)
  150. -- This command also deals with argument-less functions like "fork". For example an
  151. -- argument-less function returning an integer shall be marked with
  152. -- "()", the empty argument lt, otherwe the C compiler will
  153. -- interpret it as the address of the call casted to an integer.
  154. local
  155. i, last: INTEGER
  156. an_arg: C_FUNCTION_ARGUMENT
  157. do
  158. if has_arguments then
  159. log(once " (")
  160. buffer.append(once " (")
  161. -- Omit the eventual ellips
  162. if is_variadic then
  163. -- Skip the last argument
  164. last := children_count - 1
  165. else
  166. last := children_count
  167. end
  168. log(once "#(1) args: " # &children_count)
  169. from
  170. i := 1
  171. until
  172. i > last - 1
  173. loop
  174. an_arg := argument(i)
  175. an_arg.set_pos(i)
  176. an_arg.put_on(buffer) -- argument(i).put_on(buffer)
  177. buffer.append(once "; ")
  178. i := i + 1
  179. end
  180. an_arg := argument(last)
  181. an_arg.set_pos(last)
  182. an_arg.put_on(buffer)
  183. log(once ")")
  184. buffer.append(once ")")
  185. end
  186. end
  187. append_return_type
  188. -- Append the Eiffel equivalent type of the return type of
  189. -- Current node to `buffer' and the "is" keyword, i.e. ": INTEGER_32 is " or ":
  190. -- POINTER is". When result of `a_node' is "void" only " is" is appended.
  191. do
  192. if return_type.is_void then
  193. -- don't print anything; the correct "return type" of a C
  194. -- function returning void (i.e. a command) is an empty string.
  195. else
  196. buffer.append(once ": ")
  197. buffer.append(return_type.wrapper_type)
  198. end
  199. buffer.append(once " %N")
  200. rescue
  201. log(once "Unwrappable return type: #(1)... " # developer_exception_name)
  202. end
  203. append_body
  204. -- Append the body of function to `buffer'
  205. local
  206. description: ABSTRACT_STRING
  207. feature_name: ABSTRACT_STRING
  208. do
  209. if is_variadic then
  210. description := c_string_name & variadic_function_note
  211. else
  212. description := c_string_name
  213. end
  214. if has_arguments then
  215. feature_name := c_string_name
  216. else
  217. -- Handle the case of parameterless C functions like fork or getpid
  218. feature_name := c_string_name|"()"
  219. end
  220. buffer.append(once "%
  221. % -- #(1)%N%
  222. % external %"plug_in%"%N%
  223. % alias %"{%N%
  224. % location: %".%"%N%
  225. % module_name: %"plugin%"%N%
  226. % feature_name: %"#(2)%"%N%
  227. % }%"%N%
  228. % end%N%N" #
  229. description # feature_name)
  230. -- For debugging purpose the line where the node occurred were once printed in the comment, like th:
  231. -- buffer.append(once "%
  232. -- % -- #(1) (node at line #(3))%N%
  233. -- % external %"plug_in%"%N%
  234. -- % alias %"{%N%
  235. -- % location: %".%"%N%
  236. -- % module_name: %"plugin%"%N%
  237. -- % feature_name: %"#(2)%"%N%
  238. -- % }%"%N%
  239. -- % end%N%N" #
  240. -- description # actual_c_symbol # line.out)
  241. -- th feature has been removed to make the generated classes a little more stable, avoiding unnecessary changes.
  242. end
  243. feature {} -- Implementation
  244. argument (an_index: INTEGER): C_FUNCTION_ARGUMENT
  245. -- The argument at `an_index'.
  246. do
  247. Result ?= child(an_index)
  248. ensure
  249. no_child_with_wrong_type: Result /= Void
  250. end -- invariant name.is_equal(once U"Function")
  251. end -- class C_FUNCTION
  252. -- Copyright (C) 2008-2017: Paolo Redaelli
  253. -- wrappers-generator is free software: you can redistribute it and/or modify it
  254. -- under the terms of the GNU General Public License as publhed by the Free
  255. -- Software Foundation, either version 2 of the License, or (at your option)
  256. -- any later version.
  257. -- wrappers-generator is distributed in the hope that it will be useful, but
  258. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  259. -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  260. -- more details.
  261. -- You should have received a copy of the GNU General Public License along with
  262. -- th program. If not, see <http://www.gnu.org/licenses/>.