Line data Source code
1 : /* valaccodefunction.vala
2 : *
3 : * Copyright (C) 2006-2012 Jürg Billeter
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it under the terms of the GNU Lesser General Public
7 : * License as published by the Free Software Foundation; either
8 : * version 2.1 of the License, or (at your option) any later version.
9 :
10 : * This library is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : * Lesser General Public License for more details.
14 :
15 : * You should have received a copy of the GNU Lesser General Public
16 : * License along with this library; if not, write to the Free Software
17 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 : *
19 : * Author:
20 : * Jürg Billeter <j@bitron.ch>
21 : */
22 :
23 : using GLib;
24 :
25 : /**
26 : * Represents a function declaration in the C code.
27 : */
28 141345 : public class Vala.CCodeFunction : CCodeNode {
29 : /**
30 : * The name of this function.
31 : */
32 255197 : public string name { get; set; }
33 :
34 : /**
35 : * The function return type.
36 : */
37 244996 : public string return_type { get; set; }
38 :
39 58974 : public bool is_declaration { get; set; }
40 :
41 : /**
42 : * The function body.
43 : */
44 435679 : public CCodeBlock block { get; set; }
45 :
46 : /**
47 : * The current line directive.
48 : */
49 328719 : public CCodeLineDirective current_line { get; set; }
50 :
51 : /**
52 : * The current block to be written into.
53 : */
54 292838 : public CCodeBlock current_block { get; set; }
55 :
56 140460 : private List<CCodeParameter> parameters = new ArrayList<CCodeParameter> ();
57 :
58 140460 : List<CCodeStatement> statement_stack = new ArrayList<CCodeStatement> ();
59 :
60 210690 : public CCodeFunction (string name, string return_type = "void") {
61 70230 : this.name = name;
62 70230 : this.return_type = return_type;
63 70230 : this.block = new CCodeBlock ();
64 70230 : current_block = block;
65 : }
66 :
67 : /**
68 : * Appends the specified parameter to the list of function parameters.
69 : *
70 : * @param param a formal parameter
71 : */
72 61727 : public void add_parameter (CCodeParameter param) {
73 61727 : parameters.add (param);
74 : }
75 :
76 0 : public void insert_parameter (int position, CCodeParameter param) {
77 0 : parameters.insert (position, param);
78 : }
79 :
80 33 : public int get_parameter_count () {
81 33 : return parameters.size;
82 : }
83 :
84 64 : public CCodeParameter get_parameter (int position) {
85 64 : return parameters[position];
86 : }
87 :
88 : /**
89 : * Returns a copy of this function.
90 : *
91 : * @return copied function
92 : */
93 26318 : public CCodeFunction copy () {
94 26318 : var func = new CCodeFunction (name, return_type);
95 26318 : func.modifiers = modifiers;
96 :
97 : /* no deep copy for lists available yet
98 : * func.parameters = parameters.copy ();
99 : */
100 91222 : foreach (CCodeParameter param in parameters) {
101 32452 : func.parameters.add (param);
102 : }
103 :
104 26318 : func.is_declaration = is_declaration;
105 26318 : func.block = block;
106 26318 : return func;
107 : }
108 :
109 33000 : public override void write (CCodeWriter writer) {
110 33000 : writer.write_indent (line);
111 33000 : if (CCodeModifiers.INTERNAL in modifiers) {
112 418 : writer.write_string (GNUC_INTERNAL);
113 32582 : } else if (is_declaration && CCodeModifiers.EXTERN in modifiers) {
114 7029 : writer.write_string ("VALA_EXTERN ");
115 : }
116 33000 : if (!is_declaration && CCodeModifiers.NO_INLINE in modifiers) {
117 5 : writer.write_string (GNUC_NO_INLINE);
118 : }
119 33000 : if (CCodeModifiers.STATIC in modifiers) {
120 17860 : writer.write_string ("static ");
121 : }
122 33000 : if (CCodeModifiers.INLINE in modifiers) {
123 454 : writer.write_string ("inline ");
124 : }
125 33000 : writer.write_string (return_type);
126 33000 : if (is_declaration) {
127 14056 : writer.write_string (" ");
128 : } else {
129 18944 : writer.write_newline ();
130 : }
131 33000 : writer.write_string (name);
132 33000 : writer.write_string (" (");
133 33000 : int param_pos_begin = (is_declaration ? return_type.char_count () + 1 : 0 ) + name.char_count () + 2;
134 :
135 33000 : bool has_args = (CCodeModifiers.PRINTF in modifiers || CCodeModifiers.SCANF in modifiers);
136 33000 : int i = 0;
137 33000 : int format_arg_index = -1;
138 33000 : int args_index = -1;
139 138648 : foreach (CCodeParameter param in parameters) {
140 52824 : if (i > 0) {
141 27235 : writer.write_string (",");
142 27235 : writer.write_newline ();
143 27235 : writer.write_nspaces (param_pos_begin);
144 : }
145 52824 : param.write (writer);
146 52824 : if (CCodeModifiers.FORMAT_ARG in param.modifiers) {
147 46 : format_arg_index = i;
148 : }
149 52824 : if (has_args && param.ellipsis) {
150 : args_index = i;
151 52792 : } else if (has_args && param.type_name == "va_list" && format_arg_index < 0) {
152 14 : format_arg_index = i - 1;
153 : }
154 52824 : i++;
155 : }
156 33000 : if (i == 0) {
157 7411 : writer.write_string ("void");
158 : }
159 :
160 33000 : writer.write_string (")");
161 :
162 33000 : if (is_declaration) {
163 14056 : if (CCodeModifiers.DEPRECATED in modifiers) {
164 14 : writer.write_string (GNUC_DEPRECATED);
165 : }
166 :
167 14056 : if (CCodeModifiers.PRINTF in modifiers) {
168 21 : format_arg_index = (format_arg_index >= 0 ? format_arg_index + 1 : args_index);
169 21 : writer.write_string (GNUC_PRINTF.printf (format_arg_index, args_index + 1));
170 14035 : } else if (CCodeModifiers.SCANF in modifiers) {
171 5 : format_arg_index = (format_arg_index >= 0 ? format_arg_index + 1 : args_index);
172 5 : writer.write_string (GNUC_SCANF.printf (format_arg_index, args_index + 1));
173 14030 : } else if (format_arg_index >= 0) {
174 5 : writer.write_string (GNUC_FORMAT.printf (format_arg_index + 1));
175 : }
176 :
177 14056 : if (CCodeModifiers.CONST in modifiers) {
178 1123 : writer.write_string (GNUC_CONST);
179 : }
180 14056 : if (CCodeModifiers.UNUSED in modifiers) {
181 64 : writer.write_string (GNUC_UNUSED);
182 : }
183 :
184 14056 : if (CCodeModifiers.CONSTRUCTOR in modifiers) {
185 2 : writer.write_string (" __attribute__((constructor))");
186 14054 : } else if (CCodeModifiers.DESTRUCTOR in modifiers) {
187 2 : writer.write_string (" __attribute__((destructor))");
188 : }
189 :
190 14056 : writer.write_string (";");
191 : } else {
192 18944 : writer.write_newline ();
193 18944 : block.write (writer);
194 18944 : writer.write_newline ();
195 : }
196 33000 : writer.write_newline ();
197 : }
198 :
199 198207 : public void add_statement (CCodeNode stmt) {
200 198207 : stmt.line = current_line;
201 198207 : current_block.add_statement (stmt);
202 : }
203 :
204 4362 : public void open_block () {
205 2181 : statement_stack.add (current_block);
206 2181 : var parent_block = current_block;
207 :
208 2181 : current_block = new CCodeBlock ();
209 :
210 2181 : parent_block.add_statement (current_block);
211 : }
212 :
213 22544 : public void open_if (CCodeExpression condition) {
214 11272 : statement_stack.add (current_block);
215 11272 : var parent_block = current_block;
216 :
217 11272 : current_block = new CCodeBlock ();
218 :
219 11272 : var cif = new CCodeIfStatement (condition, current_block);
220 11272 : cif.line = current_line;
221 11272 : statement_stack.add (cif);
222 :
223 11272 : parent_block.add_statement (cif);
224 : }
225 :
226 8244 : public void add_else () {
227 4122 : current_block = new CCodeBlock ();
228 :
229 4122 : var cif = (CCodeIfStatement) statement_stack[statement_stack.size - 1];
230 4122 : cif.line = current_line;
231 4122 : assert (cif.false_statement == null);
232 4122 : cif.false_statement = current_block;
233 : }
234 :
235 1330 : public void else_if (CCodeExpression condition) {
236 665 : var parent_if = (CCodeIfStatement) statement_stack.remove_at (statement_stack.size - 1);
237 665 : assert (parent_if.false_statement == null);
238 :
239 665 : current_block = new CCodeBlock ();
240 :
241 665 : var cif = new CCodeIfStatement (condition, current_block);
242 665 : cif.line = current_line;
243 665 : parent_if.false_statement = cif;
244 665 : statement_stack.add (cif);
245 : }
246 :
247 1324 : public void open_while (CCodeExpression condition) {
248 662 : statement_stack.add (current_block);
249 662 : var parent_block = current_block;
250 :
251 662 : current_block = new CCodeBlock ();
252 :
253 662 : var cwhile = new CCodeWhileStatement (condition, current_block);
254 662 : cwhile.line = current_line;
255 662 : parent_block.add_statement (cwhile);
256 : }
257 :
258 984 : public void open_for (CCodeExpression? initializer, CCodeExpression condition, CCodeExpression? iterator) {
259 492 : statement_stack.add (current_block);
260 492 : var parent_block = current_block;
261 :
262 492 : current_block = new CCodeBlock ();
263 :
264 492 : var cfor = new CCodeForStatement (condition, current_block);
265 492 : cfor.line = current_line;
266 492 : if (initializer != null) {
267 455 : cfor.add_initializer (initializer);
268 : }
269 492 : if (iterator != null) {
270 492 : cfor.add_iterator (iterator);
271 : }
272 :
273 492 : parent_block.add_statement (cfor);
274 : }
275 :
276 1276 : public void open_switch (CCodeExpression expression) {
277 638 : statement_stack.add (current_block);
278 638 : var parent_block = current_block;
279 :
280 638 : var cswitch = new CCodeSwitchStatement (expression);
281 638 : cswitch.line = current_line;
282 638 : current_block = cswitch;
283 :
284 638 : parent_block.add_statement (cswitch);
285 : }
286 :
287 547 : public void add_label (string label) {
288 547 : add_statement (new CCodeLabel (label));
289 : }
290 :
291 1282 : public void add_case (CCodeExpression expression) {
292 1282 : add_statement (new CCodeCaseStatement (expression));
293 : }
294 :
295 634 : public void add_default () {
296 634 : add_statement (new CCodeLabel ("default"));
297 : }
298 :
299 545 : public void add_goto (string target) {
300 545 : add_statement (new CCodeGotoStatement (target));
301 : }
302 :
303 118446 : public void add_expression (CCodeExpression expression) {
304 118446 : add_statement (new CCodeExpressionStatement (expression));
305 : }
306 :
307 75054 : public void add_assignment (CCodeExpression left, CCodeExpression right) {
308 75054 : add_expression (new CCodeAssignment (left, right));
309 : }
310 :
311 10994 : public void add_return (CCodeExpression? expression = null) {
312 10994 : add_statement (new CCodeReturnStatement (expression));
313 : }
314 :
315 1872 : public void add_break () {
316 1872 : add_statement (new CCodeBreakStatement ());
317 : }
318 :
319 41 : public void add_continue () {
320 41 : add_statement (new CCodeContinueStatement ());
321 : }
322 :
323 127308 : public void add_declaration (string type_name, CCodeDeclarator declarator, CCodeModifiers modifiers = 0) {
324 63654 : var stmt = new CCodeDeclaration (type_name);
325 63654 : stmt.add_declarator (declarator);
326 63654 : stmt.modifiers = modifiers;
327 63654 : add_statement (stmt);
328 : }
329 :
330 15098 : public void close () {
331 67546 : do {
332 26224 : var top = statement_stack.remove_at (statement_stack.size - 1);
333 41322 : current_block = top as CCodeBlock;
334 26224 : } while (current_block == null);
335 : }
336 : }
|