Add AST visitors: parent links creation and semantic validator
[babeltrace.git] / formats / ctf / metadata / ctf-visitor-xml.c
1 /*
2 * ctf-visitor-xml.c
3 *
4 * Common Trace Format Metadata Visitor (XML dump).
5 *
6 * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 */
18
19 #include <stdio.h>
20 #include <unistd.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <assert.h>
24 #include <glib.h>
25 #include <inttypes.h>
26 #include <errno.h>
27 #include <babeltrace/list.h>
28 #include "ctf-scanner.h"
29 #include "ctf-parser.h"
30 #include "ctf-ast.h"
31
32 #define printf_dbg(fmt, args...) fprintf(stderr, "%s: " fmt, __func__, ## args)
33
34 static
35 void print_tabs(FILE *fd, int depth)
36 {
37 int i;
38
39 for (i = 0; i < depth; i++)
40 fprintf(fd, "\t");
41 }
42
43 static
44 int ctf_visitor_print_unary_expression(FILE *fd, int depth, struct ctf_node *node)
45 {
46 int ret = 0;
47
48 switch (node->u.unary_expression.link) {
49 case UNARY_LINK_UNKNOWN:
50 break;
51 case UNARY_DOTLINK:
52 print_tabs(fd, depth);
53 fprintf(fd, "<dotlink/>\n");
54 break;
55 case UNARY_ARROWLINK:
56 print_tabs(fd, depth);
57 fprintf(fd, "<arrowlink/>\n");
58 break;
59 case UNARY_DOTDOTDOT:
60 print_tabs(fd, depth);
61 fprintf(fd, "<dotdotdot/>\n");
62 break;
63 default:
64 fprintf(stderr, "[error] %s: unknown expression link type %d\n", __func__,
65 (int) node->u.unary_expression.link);
66 return -EINVAL;
67 }
68
69 switch (node->u.unary_expression.type) {
70 case UNARY_STRING:
71 print_tabs(fd, depth);
72 fprintf(fd, "<unary_expression value=");
73 fprintf(fd, "\"%s\"", node->u.unary_expression.u.string);
74 fprintf(fd, " />\n");
75 break;
76 case UNARY_SIGNED_CONSTANT:
77 print_tabs(fd, depth);
78 fprintf(fd, "<unary_expression value=");
79 fprintf(fd, "%" PRId64, node->u.unary_expression.u.signed_constant);
80 fprintf(fd, " />\n");
81 break;
82 case UNARY_UNSIGNED_CONSTANT:
83 print_tabs(fd, depth);
84 fprintf(fd, "<unary_expression value=");
85 fprintf(fd, "%" PRIu64, node->u.unary_expression.u.signed_constant);
86 fprintf(fd, " />\n");
87 break;
88 case UNARY_SBRAC:
89 print_tabs(fd, depth);
90 fprintf(fd, "<unary_expression_sbrac>\n");
91 ret = ctf_visitor_print_unary_expression(fd, depth + 1,
92 node->u.unary_expression.u.sbrac_exp);
93 if (ret)
94 return ret;
95 print_tabs(fd, depth);
96 fprintf(fd, "</unary_expression_sbrac>\n");
97 break;
98 case UNARY_NESTED:
99 print_tabs(fd, depth);
100 fprintf(fd, "<unary_expression_nested>\n");
101 ret = ctf_visitor_print_unary_expression(fd, depth + 1,
102 node->u.unary_expression.u.nested_exp);
103 if (ret)
104 return ret;
105 print_tabs(fd, depth);
106 fprintf(fd, "</unary_expression_nested>\n");
107 break;
108
109 case UNARY_UNKNOWN:
110 default:
111 fprintf(stderr, "[error] %s: unknown expression type %d\n", __func__,
112 (int) node->u.unary_expression.type);
113 return -EINVAL;
114 }
115 return 0;
116 }
117
118 static
119 int ctf_visitor_print_type_specifier(FILE *fd, int depth, struct ctf_node *node)
120 {
121 print_tabs(fd, depth);
122 fprintf(fd, "<type_specifier \"");
123
124 switch (node->u.type_specifier.type) {
125 case TYPESPEC_VOID:
126 fprintf(fd, "void");
127 break;
128 case TYPESPEC_CHAR:
129 fprintf(fd, "char");
130 break;
131 case TYPESPEC_SHORT:
132 fprintf(fd, "short");
133 break;
134 case TYPESPEC_INT:
135 fprintf(fd, "int");
136 break;
137 case TYPESPEC_LONG:
138 fprintf(fd, "long");
139 break;
140 case TYPESPEC_FLOAT:
141 fprintf(fd, "float");
142 break;
143 case TYPESPEC_DOUBLE:
144 fprintf(fd, "double");
145 break;
146 case TYPESPEC_SIGNED:
147 fprintf(fd, "signed");
148 break;
149 case TYPESPEC_UNSIGNED:
150 fprintf(fd, "unsigned");
151 break;
152 case TYPESPEC_BOOL:
153 fprintf(fd, "bool");
154 break;
155 case TYPESPEC_COMPLEX:
156 fprintf(fd, "complex");
157 break;
158 case TYPESPEC_CONST:
159 fprintf(fd, "const");
160 break;
161 case TYPESPEC_ID_TYPE:
162 fprintf(fd, "%s", node->u.type_specifier.id_type);
163 break;
164
165 case TYPESPEC_UNKNOWN:
166 default:
167 fprintf(stderr, "[error] %s: unknown type specifier %d\n", __func__,
168 (int) node->u.type_specifier.type);
169 return -EINVAL;
170 }
171 fprintf(fd, "\"/>\n");
172 return 0;
173 }
174
175 static
176 int ctf_visitor_print_type_declarator(FILE *fd, int depth, struct ctf_node *node)
177 {
178 int ret = 0;
179 struct ctf_node *iter;
180
181 print_tabs(fd, depth);
182 fprintf(fd, "<type_declarator>\n");
183 depth++;
184
185 if (!cds_list_empty(&node->u.type_declarator.pointers)) {
186 print_tabs(fd, depth);
187 fprintf(fd, "<pointers>\n");
188 cds_list_for_each_entry(iter, &node->u.type_declarator.pointers,
189 siblings) {
190 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
191 if (ret)
192 return ret;
193 }
194 print_tabs(fd, depth);
195 fprintf(fd, "</pointers>\n");
196 }
197
198 switch (node->u.type_declarator.type) {
199 case TYPEDEC_ID:
200 if (node->u.type_declarator.u.id) {
201 print_tabs(fd, depth);
202 fprintf(fd, "<id \"");
203 fprintf(fd, "%s", node->u.type_declarator.u.id);
204 fprintf(fd, "\" />\n");
205 }
206 break;
207 case TYPEDEC_NESTED:
208 if (node->u.type_declarator.u.nested.type_declarator) {
209 print_tabs(fd, depth);
210 fprintf(fd, "<type_declarator>\n");
211 ret = ctf_visitor_print_xml(fd, depth + 1,
212 node->u.type_declarator.u.nested.type_declarator);
213 if (ret)
214 return ret;
215 print_tabs(fd, depth);
216 fprintf(fd, "</type_declarator>\n");
217 }
218 if (node->u.type_declarator.u.nested.length) {
219 print_tabs(fd, depth);
220 fprintf(fd, "<length>\n");
221 ret = ctf_visitor_print_xml(fd, depth + 1,
222 node->u.type_declarator.u.nested.length);
223 if (ret)
224 return ret;
225 print_tabs(fd, depth);
226 fprintf(fd, "</length>\n");
227 }
228 if (node->u.type_declarator.u.nested.abstract_array) {
229 print_tabs(fd, depth);
230 fprintf(fd, "<length>\n");
231 print_tabs(fd, depth);
232 fprintf(fd, "</length>\n");
233 }
234 if (node->u.type_declarator.bitfield_len) {
235 print_tabs(fd, depth);
236 fprintf(fd, "<bitfield_len>\n");
237 ret = ctf_visitor_print_xml(fd, depth + 1,
238 node->u.type_declarator.bitfield_len);
239 if (ret)
240 return ret;
241 print_tabs(fd, depth);
242 fprintf(fd, "</bitfield_len>\n");
243 }
244 break;
245 case TYPEDEC_UNKNOWN:
246 default:
247 fprintf(stderr, "[error] %s: unknown type declarator %d\n", __func__,
248 (int) node->u.type_declarator.type);
249 return -EINVAL;
250 }
251
252 depth--;
253 print_tabs(fd, depth);
254 fprintf(fd, "</type_declarator>\n");
255 return 0;
256 }
257
258 int ctf_visitor_print_xml(FILE *fd, int depth, struct ctf_node *node)
259 {
260 int ret = 0;
261 struct ctf_node *iter;
262
263 switch (node->type) {
264 case NODE_ROOT:
265 print_tabs(fd, depth);
266 fprintf(fd, "<root>\n");
267 cds_list_for_each_entry(iter, &node->u.root._typedef,
268 siblings) {
269 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
270 if (ret)
271 return ret;
272 }
273 cds_list_for_each_entry(iter, &node->u.root.typealias,
274 siblings) {
275 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
276 if (ret)
277 return ret;
278 }
279 cds_list_for_each_entry(iter, &node->u.root.declaration_specifier, siblings) {
280 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
281 if (ret)
282 return ret;
283 }
284 cds_list_for_each_entry(iter, &node->u.root.trace, siblings) {
285 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
286 if (ret)
287 return ret;
288 }
289 cds_list_for_each_entry(iter, &node->u.root.stream, siblings) {
290 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
291 if (ret)
292 return ret;
293 }
294 cds_list_for_each_entry(iter, &node->u.root.event, siblings) {
295 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
296 if (ret)
297 return ret;
298 }
299 print_tabs(fd, depth);
300 fprintf(fd, "</root>\n");
301 break;
302
303 case NODE_EVENT:
304 print_tabs(fd, depth);
305 fprintf(fd, "<event>\n");
306 cds_list_for_each_entry(iter, &node->u.event.declaration_list, siblings) {
307 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
308 if (ret)
309 return ret;
310 }
311 print_tabs(fd, depth);
312 fprintf(fd, "</event>\n");
313 break;
314 case NODE_STREAM:
315 print_tabs(fd, depth);
316 fprintf(fd, "<stream>\n");
317 cds_list_for_each_entry(iter, &node->u.stream.declaration_list, siblings) {
318 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
319 if (ret)
320 return ret;
321 }
322 print_tabs(fd, depth);
323 fprintf(fd, "</stream>\n");
324 break;
325 case NODE_TRACE:
326 print_tabs(fd, depth);
327 fprintf(fd, "<trace>\n");
328 cds_list_for_each_entry(iter, &node->u.trace.declaration_list, siblings) {
329 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
330 if (ret)
331 return ret;
332 }
333 print_tabs(fd, depth);
334 fprintf(fd, "</trace>\n");
335 break;
336
337 case NODE_CTF_EXPRESSION:
338 print_tabs(fd, depth);
339 fprintf(fd, "<ctf_expression>\n");
340 depth++;
341 print_tabs(fd, depth);
342 fprintf(fd, "<left>\n");
343 cds_list_for_each_entry(iter, &node->u.ctf_expression.left, siblings) {
344 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
345 if (ret)
346 return ret;
347 }
348
349 print_tabs(fd, depth);
350 fprintf(fd, "</left>\n");
351
352 print_tabs(fd, depth);
353 fprintf(fd, "<right>\n");
354 cds_list_for_each_entry(iter, &node->u.ctf_expression.right, siblings) {
355 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
356 if (ret)
357 return ret;
358 }
359 print_tabs(fd, depth);
360 fprintf(fd, "</right>\n");
361 depth--;
362 print_tabs(fd, depth);
363 fprintf(fd, "</ctf_expression>\n");
364 break;
365 case NODE_UNARY_EXPRESSION:
366 return ctf_visitor_print_unary_expression(fd, depth, node);
367
368 case NODE_TYPEDEF:
369 print_tabs(fd, depth);
370 fprintf(fd, "<typedef>\n");
371 depth++;
372 print_tabs(fd, depth);
373 fprintf(fd, "<declaration_specifier>\n");
374 cds_list_for_each_entry(iter, &node->u._typedef.declaration_specifier, siblings) {
375 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
376 if (ret)
377 return ret;
378 }
379 print_tabs(fd, depth);
380 fprintf(fd, "</declaration_specifier>\n");
381
382 print_tabs(fd, depth);
383 fprintf(fd, "<type_declarators>\n");
384 cds_list_for_each_entry(iter, &node->u._typedef.type_declarators, siblings) {
385 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
386 if (ret)
387 return ret;
388 }
389 print_tabs(fd, depth);
390 fprintf(fd, "</type_declarators>\n");
391 depth--;
392 print_tabs(fd, depth);
393 fprintf(fd, "</typedef>\n");
394 break;
395 case NODE_TYPEALIAS_TARGET:
396 print_tabs(fd, depth);
397 fprintf(fd, "<target>\n");
398 depth++;
399
400 print_tabs(fd, depth);
401 fprintf(fd, "<declaration_specifier>\n");
402 cds_list_for_each_entry(iter, &node->u.typealias_target.declaration_specifier, siblings) {
403 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
404 if (ret)
405 return ret;
406 }
407 print_tabs(fd, depth);
408 fprintf(fd, "</declaration_specifier>\n");
409
410 print_tabs(fd, depth);
411 fprintf(fd, "<type_declarators>\n");
412 cds_list_for_each_entry(iter, &node->u.typealias_target.type_declarators, siblings) {
413 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
414 if (ret)
415 return ret;
416 }
417 print_tabs(fd, depth);
418 fprintf(fd, "</type_declarators>\n");
419
420 depth--;
421 print_tabs(fd, depth);
422 fprintf(fd, "</target>\n");
423 break;
424 case NODE_TYPEALIAS_ALIAS:
425 print_tabs(fd, depth);
426 fprintf(fd, "<alias>\n");
427 depth++;
428
429 print_tabs(fd, depth);
430 fprintf(fd, "<declaration_specifier>\n");
431 cds_list_for_each_entry(iter, &node->u.typealias_alias.declaration_specifier, siblings) {
432 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
433 if (ret)
434 return ret;
435 }
436 print_tabs(fd, depth);
437 fprintf(fd, "</declaration_specifier>\n");
438
439 print_tabs(fd, depth);
440 fprintf(fd, "<type_declarators>\n");
441 cds_list_for_each_entry(iter, &node->u.typealias_alias.type_declarators, siblings) {
442 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
443 if (ret)
444 return ret;
445 }
446 print_tabs(fd, depth);
447 fprintf(fd, "</type_declarators>\n");
448
449 depth--;
450 print_tabs(fd, depth);
451 fprintf(fd, "</alias>\n");
452 break;
453 case NODE_TYPEALIAS:
454 print_tabs(fd, depth);
455 fprintf(fd, "<typealias>\n");
456 ret = ctf_visitor_print_xml(fd, depth + 1, node->u.typealias.target);
457 if (ret)
458 return ret;
459 ret = ctf_visitor_print_xml(fd, depth + 1, node->u.typealias.alias);
460 if (ret)
461 return ret;
462 print_tabs(fd, depth);
463 fprintf(fd, "</typealias>\n");
464 break;
465
466 case NODE_TYPE_SPECIFIER:
467 ret = ctf_visitor_print_type_specifier(fd, depth, node);
468 if (ret)
469 return ret;
470 break;
471 case NODE_POINTER:
472 print_tabs(fd, depth);
473 if (node->u.pointer.const_qualifier)
474 fprintf(fd, "<const_pointer />\n");
475 else
476 fprintf(fd, "<pointer />\n");
477 break;
478 case NODE_TYPE_DECLARATOR:
479 ret = ctf_visitor_print_type_declarator(fd, depth, node);
480 if (ret)
481 return ret;
482 break;
483
484 case NODE_FLOATING_POINT:
485 print_tabs(fd, depth);
486 fprintf(fd, "<floating_point>\n");
487 cds_list_for_each_entry(iter, &node->u.floating_point.expressions, siblings) {
488 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
489 if (ret)
490 return ret;
491 }
492 print_tabs(fd, depth);
493 fprintf(fd, "</floating_point>\n");
494 break;
495 case NODE_INTEGER:
496 print_tabs(fd, depth);
497 fprintf(fd, "<integer>\n");
498 cds_list_for_each_entry(iter, &node->u.integer.expressions, siblings) {
499 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
500 if (ret)
501 return ret;
502 }
503 print_tabs(fd, depth);
504 fprintf(fd, "</integer>\n");
505 break;
506 case NODE_STRING:
507 print_tabs(fd, depth);
508 fprintf(fd, "<string>\n");
509 cds_list_for_each_entry(iter, &node->u.string.expressions, siblings) {
510 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
511 if (ret)
512 return ret;
513 }
514 print_tabs(fd, depth);
515 fprintf(fd, "</string>\n");
516 break;
517 case NODE_ENUMERATOR:
518 print_tabs(fd, depth);
519 fprintf(fd, "<enumerator");
520 if (node->u.enumerator.id)
521 fprintf(fd, " id=\"%s\"", node->u.enumerator.id);
522 fprintf(fd, ">\n");
523 cds_list_for_each_entry(iter, &node->u.enumerator.values, siblings) {
524 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
525 if (ret)
526 return ret;
527 }
528 print_tabs(fd, depth);
529 fprintf(fd, "</enumerator>\n");
530 break;
531 case NODE_ENUM:
532 print_tabs(fd, depth);
533 if (node->u._struct.name)
534 fprintf(fd, "<enum name=\"%s\">\n",
535 node->u._enum.enum_id);
536 else
537 fprintf(fd, "<enum >\n");
538 depth++;
539
540 if (node->u._enum.container_type) {
541 print_tabs(fd, depth);
542 fprintf(fd, "<container_type>\n");
543 ret = ctf_visitor_print_xml(fd, depth + 1, node->u._enum.container_type);
544 if (ret)
545 return ret;
546 print_tabs(fd, depth);
547 fprintf(fd, "</container_type>\n");
548 }
549
550 print_tabs(fd, depth);
551 fprintf(fd, "<enumerator_list>\n");
552 cds_list_for_each_entry(iter, &node->u._enum.enumerator_list, siblings) {
553 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
554 if (ret)
555 return ret;
556 }
557 print_tabs(fd, depth);
558 fprintf(fd, "</enumerator_list>\n");
559
560 depth--;
561 print_tabs(fd, depth);
562 fprintf(fd, "</enum>\n");
563 break;
564 case NODE_STRUCT_OR_VARIANT_DECLARATION:
565 print_tabs(fd, depth);
566 fprintf(fd, "<declaration_specifier>\n");
567 cds_list_for_each_entry(iter, &node->u.struct_or_variant_declaration.declaration_specifier, siblings) {
568 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
569 if (ret)
570 return ret;
571 }
572 print_tabs(fd, depth);
573 fprintf(fd, "</declaration_specifier>\n");
574
575 print_tabs(fd, depth);
576 fprintf(fd, "<type_declarators>\n");
577 cds_list_for_each_entry(iter, &node->u.struct_or_variant_declaration.type_declarators, siblings) {
578 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
579 if (ret)
580 return ret;
581 }
582 print_tabs(fd, depth);
583 fprintf(fd, "</type_declarators>\n");
584 break;
585 case NODE_VARIANT:
586 print_tabs(fd, depth);
587 fprintf(fd, "<variant");
588 if (node->u.variant.name)
589 fprintf(fd, " name=\"%s\"", node->u.variant.name);
590 if (node->u.variant.choice)
591 fprintf(fd, " choice=\"%s\"", node->u.variant.choice);
592 fprintf(fd, ">\n");
593 cds_list_for_each_entry(iter, &node->u.variant.declaration_list, siblings) {
594 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
595 if (ret)
596 return ret;
597 }
598 print_tabs(fd, depth);
599 fprintf(fd, "</variant>\n");
600 break;
601 case NODE_STRUCT:
602 print_tabs(fd, depth);
603 if (node->u._struct.name)
604 fprintf(fd, "<struct name=\"%s\">\n",
605 node->u._struct.name);
606 else
607 fprintf(fd, "<struct>\n");
608 cds_list_for_each_entry(iter, &node->u._struct.declaration_list, siblings) {
609 ret = ctf_visitor_print_xml(fd, depth + 1, iter);
610 if (ret)
611 return ret;
612 }
613 print_tabs(fd, depth);
614 fprintf(fd, "</struct>\n");
615 break;
616
617 case NODE_UNKNOWN:
618 default:
619 fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
620 (int) node->type);
621 return -EINVAL;
622 }
623 return ret;
624 }
This page took 0.043048 seconds and 5 git commands to generate.