girparser: Support async constructors.
[vala-lang.git] / gobject-introspection / gidlwriter.c
blob2c0cbaa5c829285e5eeef283cdb2d90750f9bd0f
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 gchar *tmp = g_markup_printf_escaped (" symbol=\"%s\"", node->symbol);
143 markup_s = g_string_append (markup_s, tmp);
144 g_free (tmp);
147 if (node->deprecated)
148 markup_s = g_string_append (markup_s, " deprecated=\"1\"");
150 g_string_append (markup_s, ">\n");
152 g_writer_write_indent (writer, markup_s->str);
153 g_string_free (markup_s, TRUE);
155 markup =
156 g_markup_printf_escaped ("<return-type type=\"%s\"/>\n",
157 node->result->type->unparsed);
158 g_writer_write (writer, markup);
159 g_free (markup);
161 if (node->parameters != NULL)
163 GList *l;
164 g_writer_write_indent (writer, "<parameters>\n");
165 for (l = node->parameters; l != NULL; l = l->next)
167 GIdlNodeParam *param = l->data;
168 markup =
169 g_markup_printf_escaped ("<parameter name=\"%s\" type=\"%s\"/>\n",
170 param->node.name, param->type->unparsed);
171 g_writer_write (writer, markup);
172 g_free (markup);
174 g_writer_write_unindent (writer, "</parameters>\n");
176 markup = g_strdup_printf ("</%s>\n", tag_name);
177 g_writer_write_unindent (writer, markup);
178 g_free (markup);
181 static void
182 vfunc_generate (GIdlWriter * writer, GIdlNodeVFunc * node)
184 char *markup =
185 g_markup_printf_escaped ("<vfunc name=\"%s\">\n", node->node.name);
186 g_writer_write_indent (writer, markup);
187 g_free (markup);
188 markup =
189 g_markup_printf_escaped ("<return-type type=\"%s\"/>\n",
190 node->result->type->unparsed);
191 g_writer_write (writer, markup);
192 g_free (markup);
193 if (node->parameters != NULL)
195 GList *l;
196 g_writer_write_indent (writer, "<parameters>\n");
197 for (l = node->parameters; l != NULL; l = l->next)
199 GIdlNodeParam *param = l->data;
200 markup =
201 g_markup_printf_escaped ("<parameter name=\"%s\" type=\"%s\"/>\n",
202 param->node.name, param->type->unparsed);
203 g_writer_write (writer, markup);
204 g_free (markup);
206 g_writer_write_unindent (writer, "</parameters>\n");
208 g_writer_write_unindent (writer, "</vfunc>\n");
211 static void
212 signal_generate (GIdlWriter * writer, GIdlNodeSignal * node)
214 char *markup;
215 const char *when = "LAST";
216 if (node->run_first)
218 when = "FIRST";
220 else if (node->run_cleanup)
222 when = "CLEANUP";
224 markup =
225 g_markup_printf_escaped ("<signal name=\"%s\" when=\"%s\">\n",
226 node->node.name, when);
227 g_writer_write_indent (writer, markup);
228 g_free (markup);
229 markup =
230 g_markup_printf_escaped ("<return-type type=\"%s\"/>\n",
231 node->result->type->unparsed);
232 g_writer_write (writer, markup);
233 g_free (markup);
234 if (node->parameters != NULL)
236 GList *l;
237 g_writer_write_indent (writer, "<parameters>\n");
238 for (l = node->parameters; l != NULL; l = l->next)
240 GIdlNodeParam *param = l->data;
241 markup =
242 g_markup_printf_escaped ("<parameter name=\"%s\" type=\"%s\"/>\n",
243 param->node.name, param->type->unparsed);
244 g_writer_write (writer, markup);
245 g_free (markup);
247 g_writer_write_unindent (writer, "</parameters>\n");
249 g_writer_write_unindent (writer, "</signal>\n");
252 static void
253 interface_generate (GIdlWriter * writer, GIdlNodeInterface * node)
255 GList *l;
256 char *markup;
257 if (node->node.type == G_IDL_NODE_OBJECT)
259 markup =
260 g_markup_printf_escaped ("<object name=\"%s\" "
261 "parent=\"%s\" "
262 "type-name=\"%s\" "
263 "get-type=\"%s\">\n",
264 node->node.name,
265 node->parent,
266 node->gtype_name,
267 node->gtype_init);
269 else if (node->node.type == G_IDL_NODE_INTERFACE)
271 markup =
272 g_markup_printf_escaped
273 ("<interface name=\"%s\" type-name=\"%s\" get-type=\"%s\">\n",
274 node->node.name, node->gtype_name, node->gtype_init);
277 g_writer_write_indent (writer, markup);
278 g_free (markup);
279 if (node->node.type == G_IDL_NODE_OBJECT && node->interfaces != NULL)
281 GList *l;
282 g_writer_write_indent (writer, "<implements>\n");
283 for (l = node->interfaces; l != NULL; l = l->next)
285 markup =
286 g_markup_printf_escaped ("<interface name=\"%s\"/>\n",
287 (char *) l->data);
288 g_writer_write (writer, markup);
289 g_free (markup);
291 g_writer_write_unindent (writer, "</implements>\n");
293 else if (node->node.type == G_IDL_NODE_INTERFACE
294 && node->prerequisites != NULL)
296 GList *l;
297 g_writer_write_indent (writer, "<requires>\n");
298 for (l = node->prerequisites; l != NULL; l = l->next)
300 markup =
301 g_markup_printf_escaped ("<interface name=\"%s\"/>\n",
302 (char *) l->data);
303 g_writer_write (writer, markup);
304 g_free (markup);
306 g_writer_write_unindent (writer, "</requires>\n");
309 for (l = node->members; l != NULL; l = l->next)
311 node_generate (writer, l->data);
314 if (node->node.type == G_IDL_NODE_OBJECT)
316 g_writer_write_unindent (writer, "</object>\n");
318 else if (node->node.type == G_IDL_NODE_INTERFACE)
320 g_writer_write_unindent (writer, "</interface>\n");
324 static void
325 struct_generate (GIdlWriter * writer, GIdlNodeStruct * node)
327 GList *l;
328 char *markup =
329 g_markup_printf_escaped ("<struct name=\"%s\">\n", node->node.name);
330 g_writer_write_indent (writer, markup);
331 g_free (markup);
332 for (l = node->members; l != NULL; l = l->next)
334 node_generate (writer, l->data);
336 g_writer_write_unindent (writer, "</struct>\n");
339 static void
340 union_generate (GIdlWriter * writer, GIdlNodeUnion * node)
342 GList *l;
343 char *markup =
344 g_markup_printf_escaped ("<union name=\"%s\">\n", node->node.name);
345 g_writer_write_indent (writer, markup);
346 g_free (markup);
347 for (l = node->members; l != NULL; l = l->next)
349 node_generate (writer, l->data);
351 g_writer_write_unindent (writer, "</union>\n");
354 static void
355 boxed_generate (GIdlWriter * writer, GIdlNodeBoxed * node)
357 GList *l;
358 char *markup =
359 g_markup_printf_escaped
360 ("<boxed name=\"%s\" type-name=\"%s\" get-type=\"%s\">\n",
361 node->node.name, node->gtype_name, node->gtype_init);
362 g_writer_write_indent (writer, markup);
363 g_free (markup);
364 for (l = node->members; l != NULL; l = l->next)
366 node_generate (writer, l->data);
368 g_writer_write_unindent (writer, "</boxed>\n");
371 static void
372 enum_generate (GIdlWriter * writer, GIdlNodeEnum * node)
374 GList *l;
375 GString *markup_s;
376 char *markup;
377 const char *tag_name = NULL;
379 if (node->node.type == G_IDL_NODE_ENUM)
381 tag_name = "enum";
383 else if (node->node.type == G_IDL_NODE_FLAGS)
385 tag_name = "flags";
388 markup_s = g_string_new ("<");
389 g_string_append_printf (markup_s,
390 "%s name=\"%s\"",
391 tag_name, node->node.name);
393 if (node->gtype_name != NULL) {
394 gchar *tmp = g_markup_printf_escaped (" type-name=\"%s\"", node->gtype_name);
395 markup_s = g_string_append (markup_s, tmp);
396 g_free (tmp);
398 if (node->gtype_init != NULL) {
399 gchar *tmp = g_markup_printf_escaped (" get-type=\"%s\"", node->gtype_init);
400 markup_s = g_string_append (markup_s, tmp);
401 g_free(tmp);
404 if (node->deprecated)
405 markup_s = g_string_append (markup_s, " deprecated=\"1\"");
407 markup_s = g_string_append (markup_s, ">\n");
409 g_writer_write_indent (writer, markup_s->str);
410 g_string_free (markup_s, TRUE);
412 for (l = node->values; l != NULL; l = l->next)
414 node_generate (writer, l->data);
417 markup = g_strdup_printf ("</%s>\n", tag_name);
418 g_writer_write_unindent (writer, markup);
419 g_free (markup);
422 static void
423 node_generate (GIdlWriter * writer, GIdlNode * node)
425 switch (node->type)
427 case G_IDL_NODE_FUNCTION:
428 case G_IDL_NODE_CALLBACK:
429 function_generate (writer, (GIdlNodeFunction *) node);
430 break;
431 case G_IDL_NODE_VFUNC:
432 vfunc_generate (writer, (GIdlNodeVFunc *) node);
433 break;
434 case G_IDL_NODE_OBJECT:
435 case G_IDL_NODE_INTERFACE:
436 interface_generate (writer, (GIdlNodeInterface *) node);
437 break;
438 case G_IDL_NODE_STRUCT:
439 struct_generate (writer, (GIdlNodeStruct *) node);
440 break;
441 case G_IDL_NODE_UNION:
442 union_generate (writer, (GIdlNodeUnion *) node);
443 break;
444 case G_IDL_NODE_BOXED:
445 boxed_generate (writer, (GIdlNodeBoxed *) node);
446 break;
447 case G_IDL_NODE_ENUM:
448 case G_IDL_NODE_FLAGS:
449 enum_generate (writer, (GIdlNodeEnum *) node);
450 break;
451 case G_IDL_NODE_PROPERTY:
452 property_generate (writer, (GIdlNodeProperty *) node);
453 break;
454 case G_IDL_NODE_FIELD:
455 field_generate (writer, (GIdlNodeField *) node);
456 break;
457 case G_IDL_NODE_SIGNAL:
458 signal_generate (writer, (GIdlNodeSignal *) node);
459 break;
460 case G_IDL_NODE_VALUE:
461 value_generate (writer, (GIdlNodeValue *) node);
462 break;
463 case G_IDL_NODE_CONSTANT:
464 constant_generate (writer, (GIdlNodeConstant *) node);
465 break;
466 default:
467 g_assert_not_reached ();
471 static void
472 g_writer_write_module (GIdlWriter * writer, GIdlModule * module)
474 GList *l;
475 char *markup =
476 g_markup_printf_escaped ("<namespace name=\"%s\">\n", module->name);
477 g_writer_write_indent (writer, markup);
478 g_free (markup);
479 for (l = module->entries; l != NULL; l = l->next)
481 node_generate (writer, l->data);
483 g_writer_write_unindent (writer, "</namespace>\n");
486 void
487 g_idl_writer_save_file (GIdlModule *module,
488 const gchar *filename)
490 GIdlWriter *writer;
492 writer = g_new0 (GIdlWriter, 1);
494 if (!filename)
495 writer->output = stdout;
496 else
497 writer->output = fopen (filename, "w");
499 g_writer_write (writer, "<?xml version=\"1.0\"?>\n");
500 g_writer_write_indent (writer, "<api version=\"1.0\">\n");
501 g_writer_write_module (writer, module);
502 g_writer_write_unindent (writer, "</api>\n");
504 if (filename)
505 fclose (writer->output);
507 g_free (writer);