Support methods returning null-terminated arrays
[vala-lang.git] / gobject-introspection / gidlwriter.c
blob5caac5e5e879ca7aa8b4aa8509e2d3dea0ad3718
1 /* GObject introspection: gen-introspect
3 * Copyright (C) 2007 Jürg Billeter
4 * Copyright (C) 2007 Johan Dahlin
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
21 * Author:
22 * Jürg Billeter <j@bitron.ch>
25 #include <stdio.h>
26 #include <glib.h>
27 #include "scanner.h"
28 #include "gidlnode.h"
30 typedef struct {
31 int indent;
32 FILE *output;
33 } GIdlWriter;
35 static void node_generate (GIdlWriter * writer, GIdlNode * node);
37 static void
38 g_writer_write_inline (GIdlWriter * writer, const char *s)
40 fprintf (writer->output, "%s", s);
43 static void
44 g_writer_write (GIdlWriter * writer, const char *s)
46 int i;
47 for (i = 0; i < writer->indent; i++)
49 fprintf (writer->output, "\t");
52 g_writer_write_inline (writer, s);
55 static void
56 g_writer_write_indent (GIdlWriter * writer, const char *s)
58 g_writer_write (writer, s);
59 writer->indent++;
62 static void
63 g_writer_write_unindent (GIdlWriter * writer, const char *s)
65 writer->indent--;
66 g_writer_write (writer, s);
69 static void
70 field_generate (GIdlWriter * writer, GIdlNodeField * node)
72 char *markup =
73 g_markup_printf_escaped ("<field name=\"%s\" type=\"%s\"/>\n",
74 node->node.name, node->type->unparsed);
75 g_writer_write (writer, markup);
76 g_free (markup);
79 static void
80 value_generate (GIdlWriter * writer, GIdlNodeValue * node)
82 char *markup =
83 g_markup_printf_escaped ("<member name=\"%s\" value=\"%d\"/>\n",
84 node->node.name, node->value);
85 g_writer_write (writer, markup);
86 g_free (markup);
89 static void
90 constant_generate (GIdlWriter * writer, GIdlNodeConstant * node)
92 char *markup =
93 g_markup_printf_escaped
94 ("<constant name=\"%s\" type=\"%s\" value=\"%s\"/>\n", node->node.name,
95 node->type->unparsed, node->value);
96 g_writer_write (writer, markup);
97 g_free (markup);
100 static void
101 property_generate (GIdlWriter * writer, GIdlNodeProperty * node)
103 char *markup =
104 g_markup_printf_escaped ("<property name=\"%s\" "
105 "type=\"%s\" "
106 "readable=\"%s\" "
107 "writable=\"%s\" "
108 "construct=\"%s\" "
109 "construct-only=\"%s\"/>\n",
110 node->node.name,
111 node->type->unparsed,
112 node->readable ? "1" : "0",
113 node->writable ? "1" : "0",
114 node->construct ? "1" : "0",
115 node->construct_only ? "1" : "0");
116 g_writer_write (writer, markup);
117 g_free (markup);
120 static void
121 function_generate (GIdlWriter * writer, GIdlNodeFunction * node)
123 const char *tag_name;
124 GString *markup_s;
125 gchar *markup;
127 if (node->node.type == G_IDL_NODE_CALLBACK)
128 tag_name = "callback";
129 else if (node->is_constructor)
130 tag_name = "constructor";
131 else if (node->is_method)
132 tag_name = "method";
133 else
134 tag_name = "function";
136 markup_s = g_string_new ("<");
137 g_string_append_printf (markup_s,
138 "%s name=\"%s\"",
139 tag_name, node->node.name);
141 if (node->node.type != G_IDL_NODE_CALLBACK)
142 g_string_append_printf (markup_s,
143 g_markup_printf_escaped (" symbol=\"%s\"", node->symbol));
145 if (node->deprecated)
146 g_string_append_printf (markup_s, " deprecated=\"1\"");
148 g_string_append (markup_s, ">\n");
150 g_writer_write_indent (writer, markup_s->str);
151 g_string_free (markup_s, TRUE);
153 markup =
154 g_markup_printf_escaped ("<return-type type=\"%s\"/>\n",
155 node->result->type->unparsed);
156 g_writer_write (writer, markup);
157 g_free (markup);
159 if (node->parameters != NULL)
161 GList *l;
162 g_writer_write_indent (writer, "<parameters>\n");
163 for (l = node->parameters; l != NULL; l = l->next)
165 GIdlNodeParam *param = l->data;
166 markup =
167 g_markup_printf_escaped ("<parameter name=\"%s\" type=\"%s\"/>\n",
168 param->node.name, param->type->unparsed);
169 g_writer_write (writer, markup);
170 g_free (markup);
172 g_writer_write_unindent (writer, "</parameters>\n");
174 markup = g_strdup_printf ("</%s>\n", tag_name);
175 g_writer_write_unindent (writer, markup);
176 g_free (markup);
179 static void
180 vfunc_generate (GIdlWriter * writer, GIdlNodeVFunc * node)
182 char *markup =
183 g_markup_printf_escaped ("<vfunc name=\"%s\">\n", node->node.name);
184 g_writer_write_indent (writer, markup);
185 g_free (markup);
186 markup =
187 g_markup_printf_escaped ("<return-type type=\"%s\"/>\n",
188 node->result->type->unparsed);
189 g_writer_write (writer, markup);
190 g_free (markup);
191 if (node->parameters != NULL)
193 GList *l;
194 g_writer_write_indent (writer, "<parameters>\n");
195 for (l = node->parameters; l != NULL; l = l->next)
197 GIdlNodeParam *param = l->data;
198 markup =
199 g_markup_printf_escaped ("<parameter name=\"%s\" type=\"%s\"/>\n",
200 param->node.name, param->type->unparsed);
201 g_writer_write (writer, markup);
202 g_free (markup);
204 g_writer_write_unindent (writer, "</parameters>\n");
206 g_writer_write_unindent (writer, "</vfunc>\n");
209 static void
210 signal_generate (GIdlWriter * writer, GIdlNodeSignal * node)
212 char *markup;
213 const char *when = "LAST";
214 if (node->run_first)
216 when = "FIRST";
218 else if (node->run_cleanup)
220 when = "CLEANUP";
222 markup =
223 g_markup_printf_escaped ("<signal name=\"%s\" when=\"%s\">\n",
224 node->node.name, when);
225 g_writer_write_indent (writer, markup);
226 g_free (markup);
227 markup =
228 g_markup_printf_escaped ("<return-type type=\"%s\"/>\n",
229 node->result->type->unparsed);
230 g_writer_write (writer, markup);
231 g_free (markup);
232 if (node->parameters != NULL)
234 GList *l;
235 g_writer_write_indent (writer, "<parameters>\n");
236 for (l = node->parameters; l != NULL; l = l->next)
238 GIdlNodeParam *param = l->data;
239 markup =
240 g_markup_printf_escaped ("<parameter name=\"%s\" type=\"%s\"/>\n",
241 param->node.name, param->type->unparsed);
242 g_writer_write (writer, markup);
243 g_free (markup);
245 g_writer_write_unindent (writer, "</parameters>\n");
247 g_writer_write_unindent (writer, "</signal>\n");
250 static void
251 interface_generate (GIdlWriter * writer, GIdlNodeInterface * node)
253 GList *l;
254 char *markup;
255 if (node->node.type == G_IDL_NODE_OBJECT)
257 markup =
258 g_markup_printf_escaped ("<object name=\"%s\" "
259 "parent=\"%s\" "
260 "type-name=\"%s\" "
261 "get-type=\"%s\">\n",
262 node->node.name,
263 node->parent,
264 node->gtype_name,
265 node->gtype_init);
267 else if (node->node.type == G_IDL_NODE_INTERFACE)
269 markup =
270 g_markup_printf_escaped
271 ("<interface name=\"%s\" type-name=\"%s\" get-type=\"%s\">\n",
272 node->node.name, node->gtype_name, node->gtype_init);
275 g_writer_write_indent (writer, markup);
276 g_free (markup);
277 if (node->node.type == G_IDL_NODE_OBJECT && node->interfaces != NULL)
279 GList *l;
280 g_writer_write_indent (writer, "<implements>\n");
281 for (l = node->interfaces; l != NULL; l = l->next)
283 markup =
284 g_markup_printf_escaped ("<interface name=\"%s\"/>\n",
285 (char *) l->data);
286 g_writer_write (writer, markup);
287 g_free (markup);
289 g_writer_write_unindent (writer, "</implements>\n");
291 else if (node->node.type == G_IDL_NODE_INTERFACE
292 && node->prerequisites != NULL)
294 GList *l;
295 g_writer_write_indent (writer, "<requires>\n");
296 for (l = node->prerequisites; l != NULL; l = l->next)
298 markup =
299 g_markup_printf_escaped ("<interface name=\"%s\"/>\n",
300 (char *) l->data);
301 g_writer_write (writer, markup);
302 g_free (markup);
304 g_writer_write_unindent (writer, "</requires>\n");
307 for (l = node->members; l != NULL; l = l->next)
309 node_generate (writer, l->data);
312 if (node->node.type == G_IDL_NODE_OBJECT)
314 g_writer_write_unindent (writer, "</object>\n");
316 else if (node->node.type == G_IDL_NODE_INTERFACE)
318 g_writer_write_unindent (writer, "</interface>\n");
322 static void
323 struct_generate (GIdlWriter * writer, GIdlNodeStruct * node)
325 GList *l;
326 char *markup =
327 g_markup_printf_escaped ("<struct name=\"%s\">\n", node->node.name);
328 g_writer_write_indent (writer, markup);
329 g_free (markup);
330 for (l = node->members; l != NULL; l = l->next)
332 node_generate (writer, l->data);
334 g_writer_write_unindent (writer, "</struct>\n");
337 static void
338 union_generate (GIdlWriter * writer, GIdlNodeUnion * node)
340 GList *l;
341 char *markup =
342 g_markup_printf_escaped ("<union name=\"%s\">\n", node->node.name);
343 g_writer_write_indent (writer, markup);
344 g_free (markup);
345 for (l = node->members; l != NULL; l = l->next)
347 node_generate (writer, l->data);
349 g_writer_write_unindent (writer, "</union>\n");
352 static void
353 boxed_generate (GIdlWriter * writer, GIdlNodeBoxed * node)
355 GList *l;
356 char *markup =
357 g_markup_printf_escaped
358 ("<boxed name=\"%s\" type-name=\"%s\" get-type=\"%s\">\n",
359 node->node.name, node->gtype_name, node->gtype_init);
360 g_writer_write_indent (writer, markup);
361 g_free (markup);
362 for (l = node->members; l != NULL; l = l->next)
364 node_generate (writer, l->data);
366 g_writer_write_unindent (writer, "</boxed>\n");
369 static void
370 enum_generate (GIdlWriter * writer, GIdlNodeEnum * node)
372 GList *l;
373 GString *markup_s;
374 char *markup;
375 const char *tag_name = NULL;
377 if (node->node.type == G_IDL_NODE_ENUM)
379 tag_name = "enum";
381 else if (node->node.type == G_IDL_NODE_FLAGS)
383 tag_name = "flags";
386 markup_s = g_string_new ("<");
387 g_string_append_printf (markup_s,
388 "%s name=\"%s\"",
389 tag_name, node->node.name);
391 if (node->gtype_name != NULL)
392 g_string_append_printf (markup_s,
393 g_markup_printf_escaped (" type-name=\"%s\"", node->gtype_name));
395 if (node->gtype_init != NULL)
396 g_string_append_printf (markup_s,
397 g_markup_printf_escaped (" get-type=\"%s\"", node->gtype_init));
399 if (node->deprecated)
400 g_string_append_printf (markup_s, " deprecated=\"1\"");
402 g_string_append (markup_s, ">\n");
404 g_writer_write_indent (writer, markup_s->str);
405 g_string_free (markup_s, TRUE);
407 for (l = node->values; l != NULL; l = l->next)
409 node_generate (writer, l->data);
412 markup = g_strdup_printf ("</%s>\n", tag_name);
413 g_writer_write_unindent (writer, markup);
414 g_free (markup);
417 static void
418 node_generate (GIdlWriter * writer, GIdlNode * node)
420 switch (node->type)
422 case G_IDL_NODE_FUNCTION:
423 case G_IDL_NODE_CALLBACK:
424 function_generate (writer, (GIdlNodeFunction *) node);
425 break;
426 case G_IDL_NODE_VFUNC:
427 vfunc_generate (writer, (GIdlNodeVFunc *) node);
428 break;
429 case G_IDL_NODE_OBJECT:
430 case G_IDL_NODE_INTERFACE:
431 interface_generate (writer, (GIdlNodeInterface *) node);
432 break;
433 case G_IDL_NODE_STRUCT:
434 struct_generate (writer, (GIdlNodeStruct *) node);
435 break;
436 case G_IDL_NODE_UNION:
437 union_generate (writer, (GIdlNodeUnion *) node);
438 break;
439 case G_IDL_NODE_BOXED:
440 boxed_generate (writer, (GIdlNodeBoxed *) node);
441 break;
442 case G_IDL_NODE_ENUM:
443 case G_IDL_NODE_FLAGS:
444 enum_generate (writer, (GIdlNodeEnum *) node);
445 break;
446 case G_IDL_NODE_PROPERTY:
447 property_generate (writer, (GIdlNodeProperty *) node);
448 break;
449 case G_IDL_NODE_FIELD:
450 field_generate (writer, (GIdlNodeField *) node);
451 break;
452 case G_IDL_NODE_SIGNAL:
453 signal_generate (writer, (GIdlNodeSignal *) node);
454 break;
455 case G_IDL_NODE_VALUE:
456 value_generate (writer, (GIdlNodeValue *) node);
457 break;
458 case G_IDL_NODE_CONSTANT:
459 constant_generate (writer, (GIdlNodeConstant *) node);
460 break;
461 default:
462 g_assert_not_reached ();
466 static void
467 g_writer_write_module (GIdlWriter * writer, GIdlModule * module)
469 GList *l;
470 char *markup =
471 g_markup_printf_escaped ("<namespace name=\"%s\">\n", module->name);
472 g_writer_write_indent (writer, markup);
473 g_free (markup);
474 for (l = module->entries; l != NULL; l = l->next)
476 node_generate (writer, l->data);
478 g_writer_write_unindent (writer, "</namespace>\n");
481 void
482 g_idl_writer_save_file (GIdlModule *module,
483 const gchar *filename)
485 GIdlWriter *writer;
487 writer = g_new0 (GIdlWriter, 1);
489 if (!filename)
490 writer->output = stdout;
491 else
492 writer->output = fopen (filename, "w");
494 g_writer_write (writer, "<?xml version=\"1.0\"?>\n");
495 g_writer_write_indent (writer, "<api version=\"1.0\">\n");
496 g_writer_write_module (writer, module);
497 g_writer_write_unindent (writer, "</api>\n");
499 if (filename)
500 fclose (writer->output);