PageRenderTime 12ms CodeModel.GetById 2ms app.highlight 5ms RepoModel.GetById 2ms app.codeStats 0ms

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