features
[lttv.git] / genevent-new / genevent.c
CommitLineData
92d82357 1/******************************************************************************
2 * Genevent
3 *
4 * Event generator. XML to logging C code converter.
5 *
6 * Program parameters :
7 * ./genevent name.xml
8 *
9 * Will generate ltt-facility-name.h, ltt-facility-id-name.h
10 * ltt-facility-loader-name.c, ltt-facility-loader-name.h
11 * in the current directory.
12 *
13 * Supports :
14 * - C Alignment
15 * - C types : struct, union, enum, basic types.
16 * - Architectures : LP32, ILP32, ILP64, LLP64, LP64.
17 *
18 * Additionnal structures supported :
19 * - embedded variable size strings
20 * - embedded variable size arrays
21 * - embedded variable size sequences
22 *
23 * Notes :
24 * (1)
25 * enums are limited to integer type, as this is what is used in C. Note,
26 * however, that ISO/IEC 9899:TC2 specify that the type of enum can be char,
27 * unsigned int or int. This is implementation defined (compiler). That's why we
28 * add a check for sizeof enum.
29 *
30 * (2)
31 * Because of archtecture defined type sizes, we need to ask for ltt_align
32 * (which gives the alignment) by passing basic types, not their actual sizes.
33 * It's up to ltt_align to determine sizes of types.
34 *
35 * Note that, from
36 * http://www.usenix.org/publications/login/standards/10.data.html
37 * (Andrew Josey <a.josey@opengroup.org>) :
38 *
39 * Data Type LP32 ILP32 ILP64 LLP64 LP64
40 * char 8 8 8 8 8
41 * short 16 16 16 16 16
42 * int32 32
43 * int 16 32 64 32 32
44 * long 32 32 64 32 64
45 * long long (int64) 64
46 * pointer 32 32 64 64 64
47 *
48 * With these constraints :
49 * sizeof(char) <= sizeof(short) <= sizeof(int)
50 * <= sizeof(long) = sizeof(size_t)
51 *
52 * and therefore sizeof(long) <= sizeof(pointer) <= sizeof(size_t)
53 *
54 * Which means we only have to remember which is the biggest type in a structure
55 * to know the structure's alignment.
56 */
57
2d2d14a7 58#define _GNU_SOURCE
59#include <limits.h>
60#include <stdlib.h>
92d82357 61#include <errno.h>
62#include <sys/types.h>
63#include <sys/stat.h>
64#include <fcntl.h>
65#include <stdio.h>
66#include <string.h>
67#include <unistd.h>
2d2d14a7 68#include <assert.h>
92d82357 69
70#include "genevent.h"
71#include "parser.h"
72
73
74#define TRUE 1
75#define FALSE (!TRUE)
76
2d2d14a7 77/* Debugging printf */
78#ifdef DEBUG
79#define dprintf(...) \
80 do {\
81 printf(__FILE__ ",%u,%s: ",\
82 __LINE__, __func__);\
83 printf(__VA_ARGS__);\
84 } while(0)
85#else
86#define dprintf(...)
87#endif
88
a67cd958 89void preset_field_type_size(event_t *event_type,
90 off_t offset_root, off_t offset_parent,
91 enum field_status *fixed_root, enum field_status *fixed_parent,
92 field_t *field);
2d2d14a7 93
92d82357 94/* Code printing */
95
2d2d14a7 96void print_tabs(unsigned int tabs, FILE *fd)
97{
98 for(unsigned int i = 0; i<tabs;i++)
99 fprintf(fd, "\t");
100}
101
92d82357 102/* Type size checking */
2d2d14a7 103/* Uses #error in the generated code to signal error and stop the compiler */
92d82357 104int print_check(int fd);
105
106
2d2d14a7 107/* print type.
108 *
109 * Copied from construct_types_and_fields in LTTV facility.c */
110
111int print_type(type_descriptor_t * td, FILE *fd, unsigned int tabs,
112 char *nest_name, char *field_name)
113{
114 char basename[PATH_MAX];
115 unsigned int basename_len = 0;
116
117 strcpy(basename, nest_name);
118 basename_len = strlen(basename);
119
120 /* For a named type, we use the type_name directly */
121 if(td->type_name != NULL) {
122 strncpy(basename, td->type_name, PATH_MAX);
123 basename_len = strlen(basename);
124 } else {
125 /* For a unnamed type, there must be a field name */
7b175edc 126 if((basename_len != 0)
127 && (basename[basename_len-1] != '_')
128 && (field_name[0] != '\0')) {
2d2d14a7 129 strncat(basename, "_", PATH_MAX - basename_len);
130 basename_len = strlen(basename);
131 }
132 strncat(basename, field_name, PATH_MAX - basename_len);
133 }
134
135 switch(td->type) {
136 case INT_FIXED:
137 fprintf(fd, "%s", intOutputTypes[getSizeindex(td->size)]);
138 break;
139 case UINT_FIXED:
140 fprintf(fd, "%s", uintOutputTypes[getSizeindex(td->size)]);
141 break;
142 case CHAR:
143 fprintf(fd, "signed char");
144 break;
145 case UCHAR:
146 fprintf(fd, "unsigned char");
147 break;
148 case SHORT:
149 fprintf(fd, "short");
150 break;
151 case USHORT:
152 fprintf(fd, "unsigned short");
153 break;
154 case INT:
155 fprintf(fd, "int");
156 break;
157 case UINT:
158 fprintf(fd, "unsigned int");
159 break;
160 case FLOAT:
161 fprintf(fd, "%s", floatOutputTypes[getSizeindex(td->size)]);
162 break;
163 case POINTER:
164 fprintf(fd, "void *");
165 break;
166 case LONG:
167 fprintf(fd, "long");
168 break;
169 case ULONG:
170 fprintf(fd, "unsigned long");
171 break;
172 case SIZE_T:
173 fprintf(fd, "size_t");
174 break;
175 case SSIZE_T:
176 fprintf(fd, "ssize_t");
177 break;
178 case OFF_T:
179 fprintf(fd, "off_t");
180 break;
181 case STRING:
182 fprintf(fd, "char *");
183 break;
184 case ENUM:
185 fprintf(fd, "enum lttng_%s", basename);
186 break;
187 case ARRAY:
188 fprintf(fd, "lttng_array_%s", basename);
189 break;
190 case SEQUENCE:
191 fprintf(fd, "lttng_sequence_%s", basename);
192 break;
193 case STRUCT:
194 fprintf(fd, "struct lttng_%s", basename);
195 break;
196 case UNION:
197 fprintf(fd, "union lttng_%s", basename);
198 break;
199 default:
200 printf("print_type : unknown type\n");
201 return 1;
202 }
203
204 return 0;
205}
206
7e97b039 207/* Print logging function argument */
208int print_arg(type_descriptor_t * td, FILE *fd, unsigned int tabs,
209 char *nest_name, char *field_name)
210{
211 char basename[PATH_MAX];
212 unsigned int basename_len = 0;
213
214 strcpy(basename, nest_name);
215 basename_len = strlen(basename);
216
217 /* For a named type, we use the type_name directly */
218 if(td->type_name != NULL) {
219 strncpy(basename, td->type_name, PATH_MAX);
220 basename_len = strlen(basename);
221 } else {
222 /* For a unnamed type, there must be a field name */
223 if((basename_len != 0)
224 && (basename[basename_len-1] != '_')
225 && (field_name[0] != '\0')) {
226 strncat(basename, "_", PATH_MAX - basename_len);
227 basename_len = strlen(basename);
228 }
229 strncat(basename, field_name, PATH_MAX - basename_len);
230 }
231
232 print_tabs(tabs, fd);
233
234 switch(td->type) {
235 case INT_FIXED:
236 fprintf(fd, "%s", intOutputTypes[getSizeindex(td->size)]);
237 fprintf(fd, " %s", field_name);
238 break;
239 case UINT_FIXED:
240 fprintf(fd, "%s", uintOutputTypes[getSizeindex(td->size)]);
241 fprintf(fd, " %s", field_name);
242 break;
243 case CHAR:
244 fprintf(fd, "signed char");
245 fprintf(fd, " %s", field_name);
246 break;
247 case UCHAR:
248 fprintf(fd, "unsigned char");
249 fprintf(fd, " %s", field_name);
250 break;
251 case SHORT:
252 fprintf(fd, "short");
253 fprintf(fd, " %s", field_name);
254 break;
255 case USHORT:
256 fprintf(fd, "unsigned short");
257 fprintf(fd, " %s", field_name);
258 break;
259 case INT:
260 fprintf(fd, "int");
261 fprintf(fd, " %s", field_name);
262 break;
263 case UINT:
264 fprintf(fd, "unsigned int");
265 fprintf(fd, " %s", field_name);
266 break;
267 case FLOAT:
268 fprintf(fd, "%s", floatOutputTypes[getSizeindex(td->size)]);
269 fprintf(fd, " %s", field_name);
270 break;
271 case POINTER:
272 fprintf(fd, "void *");
273 fprintf(fd, " %s", field_name);
274 break;
275 case LONG:
276 fprintf(fd, "long");
277 fprintf(fd, " %s", field_name);
278 break;
279 case ULONG:
280 fprintf(fd, "unsigned long");
281 fprintf(fd, " %s", field_name);
282 break;
283 case SIZE_T:
284 fprintf(fd, "size_t");
285 fprintf(fd, " %s", field_name);
286 break;
287 case SSIZE_T:
288 fprintf(fd, "ssize_t");
289 fprintf(fd, " %s", field_name);
290 break;
291 case OFF_T:
292 fprintf(fd, "off_t");
293 fprintf(fd, " %s", field_name);
294 break;
295 case STRING:
296 fprintf(fd, "char *");
297 fprintf(fd, " %s", field_name);
298 break;
299 case ENUM:
300 fprintf(fd, "enum lttng_%s", basename);
301 fprintf(fd, " %s", field_name);
302 break;
303 case ARRAY:
304 fprintf(fd, "lttng_array_%s", basename);
305 fprintf(fd, " %s", field_name);
306 break;
307 case SEQUENCE:
308 fprintf(fd, "lttng_sequence_%s *", basename);
309 fprintf(fd, " %s", field_name);
310 break;
311 case STRUCT:
312 fprintf(fd, "struct lttng_%s *", basename);
313 fprintf(fd, " %s", field_name);
314 break;
315 case UNION:
316 fprintf(fd, "union lttng_%s *", basename);
317 fprintf(fd, " %s", field_name);
318 break;
319 default:
320 printf("print_type : unknown type\n");
321 return 1;
322 }
323
324 return 0;
325}
326
327
2d2d14a7 328/* print type declaration.
329 *
330 * Copied from construct_types_and_fields in LTTV facility.c */
331
332int print_type_declaration(type_descriptor_t * td, FILE *fd, unsigned int tabs,
333 char *nest_name, char *field_name)
334{
335 char basename[PATH_MAX];
336 unsigned int basename_len = 0;
337
7b175edc 338 strncpy(basename, nest_name, PATH_MAX);
2d2d14a7 339 basename_len = strlen(basename);
340
341 /* For a named type, we use the type_name directly */
342 if(td->type_name != NULL) {
343 strncpy(basename, td->type_name, PATH_MAX);
344 basename_len = strlen(basename);
345 } else {
7b175edc 346 /* For a unnamed type, there must be a field name, except for
347 * the array. */
348 if((basename_len != 0)
349 && (basename[basename_len-1] != '_'
350 && (field_name[0] != '\0'))) {
2d2d14a7 351 strncat(basename, "_", PATH_MAX - basename_len);
352 basename_len = strlen(basename);
353 }
354 strncat(basename, field_name, PATH_MAX - basename_len);
2d2d14a7 355 }
356
357 switch(td->type) {
358 case ENUM:
359 fprintf(fd, "enum lttng_%s", basename);
360 fprintf(fd, " {\n");
361 for(unsigned int i=0;i<td->labels.position;i++){
362 print_tabs(1, fd);
363 fprintf(fd, "LTTNG_%s", ((char*)(td->labels.array[i])));
364 fprintf(fd, ",\n");
365 }
366 fprintf(fd, "};\n");
367 fprintf(fd, "\n");
368 break;
369
370 case ARRAY:
7b175edc 371 dprintf("%s\n", basename);
2d2d14a7 372 assert(td->size >= 0);
a67cd958 373 if(((field_t*)td->fields.array[0])->type->type_name == NULL) {
2d2d14a7 374 /* Not a named nested type : we must print its declaration first */
a67cd958 375 if(print_type_declaration(((field_t*)td->fields.array[0])->type,
2d2d14a7 376 fd, 0, basename, "")) return 1;
377 }
378 fprintf(fd, "#define LTTNG_ARRAY_SIZE_%s %llu\n", basename,
379 td->size);
7e97b039 380 fprintf(fd, "typedef ");
a67cd958 381 if(print_type(((field_t*)td->fields.array[0])->type,
382 fd, tabs, basename, "")) return 1;
2d2d14a7 383 fprintf(fd, " lttng_array_%s[LTTNG_ARRAY_SIZE_%s];\n", basename,
384 basename);
385 fprintf(fd, "\n");
386 break;
387 case SEQUENCE:
a67cd958 388 /* We assume that the sequence length type does not need to be declared.
389 */
390 if(((field_t*)td->fields.array[1])->type->type_name == NULL) {
2d2d14a7 391 /* Not a named nested type : we must print its declaration first */
a67cd958 392 if(print_type_declaration(((field_t*)td->fields.array[1])->type,
2d2d14a7 393 fd, 0, basename, "")) return 1;
394 }
395 fprintf(fd, "typedef struct lttng_sequence_%s lttng_sequence_%s;\n",
396 basename,
397 basename);
398 fprintf(fd, "struct lttng_sequence_%s", basename);
399 fprintf(fd, " {\n");
400 print_tabs(1, fd);
401 fprintf(fd, "unsigned int len;\n");
402 print_tabs(1, fd);
a67cd958 403 if(print_type(((field_t*)td->fields.array[1])->type,
404 fd, tabs, basename, "")) return 1;
2d2d14a7 405 fprintf(fd, " *array;\n");
406 fprintf(fd, "};\n");
407 fprintf(fd, "\n");
408 break;
409
410 case STRUCT:
411 for(unsigned int i=0;i<td->fields.position;i++){
412 field_t *field = (field_t*)(td->fields.array[i]);
413 type_descriptor_t *type = field->type;
414 if(type->type_name == NULL) {
415 /* Not a named nested type : we must print its declaration first */
416 if(print_type_declaration(type,
417 fd, 0, basename, field->name)) return 1;
418 }
419 }
420 fprintf(fd, "struct lttng_%s", basename);
421 fprintf(fd, " {\n");
422 for(unsigned int i=0;i<td->fields.position;i++){
423 field_t *field = (field_t*)(td->fields.array[i]);
424 type_descriptor_t *type = field->type;
425 print_tabs(1, fd);
47299663 426 if(print_type(type, fd, tabs, basename, field->name)) return 1;
2d2d14a7 427 fprintf(fd, " ");
428 fprintf(fd, "%s", field->name);
429 fprintf(fd, ";\n");
430 }
431 fprintf(fd, "};\n");
432 fprintf(fd, "\n");
433 break;
434 case UNION:
435 /* TODO : Do not allow variable length fields in a union */
436 for(unsigned int i=0;i<td->fields.position;i++){
437 field_t *field = (field_t*)(td->fields.array[i]);
438 type_descriptor_t *type = field->type;
439 if(type->type_name == NULL) {
440 /* Not a named nested type : we must print its declaration first */
47299663 441 if(print_type_declaration(type,
442 fd, 0, basename, field->name)) return 1;
2d2d14a7 443 }
444 }
445 fprintf(fd, "union lttng_%s", basename);
446 fprintf(fd, " {\n");
447 for(unsigned i=0;i<td->fields.position;i++){
448 field_t *field = (field_t*)(td->fields.array[i]);
449 type_descriptor_t *type = field->type;
450 print_tabs(1, fd);
47299663 451 if(print_type(type, fd, tabs, basename, field->name)) return 1;
2d2d14a7 452 fprintf(fd, " ");
453 fprintf(fd, "%s", field->name);
454 fprintf(fd, ";\n");
455 }
456 fprintf(fd, "};\n");
457 fprintf(fd, "\n");
458 break;
459 default:
460 dprintf("print_type_declaration : unknown type or nothing to declare.\n");
461 break;
462 }
463
464 return 0;
465}
466
a67cd958 467
468
469
470
471/*****************************************************************************
472 *Function name
473 * set_named_type_offsets : set the precomputable offset of the named type
474 *Input params
475 * type : the type
476 ****************************************************************************/
477void set_named_type_offsets(type_descriptor_t *type)
478{
479 enum field_status current_child_status = FIELD_FIXED_GENEVENT;
480 off_t current_offset = 0;
481
482 preset_type_size(
483 current_offset,
484 &current_child_status,
485 type);
486 if(current_child_status == FIELD_FIXED_GENEVENT) {
487 current_offset += type->size;
488 } else {
489 current_offset = 0;
490 }
491}
492
493
494/*****************************************************************************
495 *Function name
496 * set_event_fields_offsets : set the precomputable offset of the fields
497 *Input params
498 * event : the event
499 ****************************************************************************/
500void set_event_fields_offsets(event_t *event)
501{
502 enum field_status current_child_status = FIELD_FIXED;
503 off_t current_offset = 0;
504
505 for(unsigned int i = 0; i < event->type->fields.position; i++) {
506 /* For each field, set the field offset. */
507 field_t *child_field = (field_t*)event->type->fields.array[i];
508 type_descriptor_t *t = f->type;
509 /* Skip named types */
510 if(t->type_name != NULL) continue;
511
512 preset_type_size(
513 current_offset,
514 &current_child_status,
515 t);
516 if(current_child_status == FIELD_FIXED_GENEVENT) {
517 current_offset += type->size;
518 } else {
519 current_offset = 0;
520 }
521 }
522}
523
524
525
526/*****************************************************************************
527 *Function name
528 * print_type_size : print the fixed sizes of the field type
529 * taken from LTTV.
530 *
531 * use offset_parent as offset to calculate alignment.
532 *Input params
533 * offset_parent : offset from the parent
534 * fixed_parent : Do we know a fixed offset to the parent ?
535 * type : type
536 ****************************************************************************/
537void print_type_size(
538 off_t offset_parent,
539 enum field_status *fixed_parent,
540 type_descriptor_t *type,
541 FILE *fd,
542 char *size_name)
543{
544 enum field_status local_fixed_parent;
545 guint i;
546
547 g_assert(type->fixed_size == FIELD_UNKNOWN);
548
549 size_t current_offset;
550 enum field_status current_child_status, final_child_status;
551 size_t max_size;
552
553 switch(type->type) {
554 /* type sizes known by genevent/compiler */
555 case INT_FIXED:
556 case UINT_FIXED:
557 case FLOAT:
558 case CHAR:
559 case UCHAR:
560 case SHORT:
561 case USHORT:
562 /* Align */
563 fprintf(fd, "%s += ltt_align(%s, %s)", size_name);
564 /* Data */
565 type->fixed_size = FIELD_FIXED_GENEVENT;
566 break;
567 /* host type sizes unknown by genevent, but known by the compiler */
568 case INT:
569 case UINT:
570 case ENUM:
571 /* An enum is either : char or int. In gcc, always int. Hope
572 * it's always like this. */
573 type->fixed_size = FIELD_FIXED_COMPILER;
574 type->compiler_size = COMPILER_INT;
575 break;
576 case LONG:
577 case ULONG:
578 type->fixed_size = FIELD_FIXED_COMPILER;
579 type->compiler_size = COMPILER_LONG;
580 break;
581 case POINTER:
582 type->fixed_size = FIELD_FIXED_COMPILER;
583 type->compiler_size = COMPILER_POINTER;
584 break;
585 case SIZE_T:
586 case SSIZE_T:
587 case OFF_T:
588 type->fixed_size = FIELD_FIXED_COMPILER;
589 type->compiler_size = COMPILER_SIZE_T;
590 break;
591 /* compound types :
592 * if all children has fixed size, then the parent size can be
593 * known directly and the copy can be done efficiently.
594 * if only part of the children has fixed size, then the contiguous
595 * elements will be copied in one bulk, but the variable size elements
596 * will be copied separately. This is necessary because those variable
597 * size elements are referenced by pointer in C.
598 */
599 case SEQUENCE:
600 current_offset = 0;
601 local_fixed_parent = FIELD_FIXED_GENEVENT;
602 preset_type_size(
603 0,
604 &local_fixed_parent,
605 ((field_t*)type->fields.array[0])->type);
606 preset_field_type_size(
607 0,
608 &local_fixed_parent,
609 ((field_t*)type->fields.array[1])->type);
610 type->fixed_size = FIELD_VARIABLE;
611 *fixed_parent = FIELD_VARIABLE;
612 break;
613 case LTT_STRING:
614 field->fixed_size = FIELD_VARIABLE;
615 *fixed_parent = FIELD_VARIABLE;
616 break;
617 case LTT_ARRAY:
618 local_fixed_parent = FIELD_FIXED_GENEVENT;
619 preset_type_size(
620 0,
621 &local_fixed_parent,
622 ((field_t*)type->fields.array[0])->type);
623 type->fixed_size = local_fixed_parent;
624 if(type->fixed_size == FIELD_FIXED_GENEVENT) {
625 type->size =
626 type->element_number * ((field_t*)type->fields.array[0])->type->size;
627 } else if(type->fixed_size == FIELD_FIXED_COMPILER) {
628 type->size =
629 type->element_number;
630 } else {
631 type->size = 0;
632 *fixed_parent = FIELD_VARIABLE;
633 }
634 break;
635 case LTT_STRUCT:
636 current_offset = 0;
637 current_child_status = FIELD_FIXED_GENEVENT;
638 for(i=0;i<type->element_number;i++) {
639 preset_field_type_size(
640 current_offset,
641 &current_child_status,
642 ((field_t*)type->fields.array[i])->type);
643 if(current_child_status == FIELD_FIXED_GENEVENT) {
644 current_offset += field->child[i]->field_size;
645 } else {
646 current_offset = 0;
647 }
648 }
649 if(current_child_status != FIELD_FIXED_GENEVENT) {
650 *fixed_parent = current_child_status;
651 type->size = 0;
652 type->fixed_size = current_child_status;
653 } else {
654 type->size = current_offset;
655 type->fixed_size = FIELD_FIXED_GENEVENT;
656 }
657 break;
658 case LTT_UNION:
659 current_offset = 0;
660 max_size = 0;
661 final_child_status = FIELD_FIXED_GENEVENT;
662 for(i=0;i<type->element_number;i++) {
663 enum field_status current_child_status = FIELD_FIXED;
664 preset_field_type_size(
665 current_offset,
666 &current_child_status,
667 ((field_t*)type->fields.array[i])->type);
668 if(current_child_status != FIELD_FIXED_GENEVENT)
669 final_child_status = current_child_status;
670 else
671 max_size =
672 max(max_size, ((field_t*)type->fields.array[i])->type->size);
673 }
674 if(final_child_status != FIELD_FIXED_GENEVENT AND COMPILER) {
675 g_error("LTTV does not support variable size fields in unions.");
676 /* This will stop the application. */
677 *fixed_parent = final_child_status;
678 type->size = 0;
679 type->fixed_size = current_child_status;
680 } else {
681 type->size = max_size;
682 type->fixed_size = FIELD_FIXED_GENEVENT;
683 }
684 break;
685 }
686
687}
688
689
690size_t get_field_type_size(LttTracefile *tf, LttEventType *event_type,
691 off_t offset_root, off_t offset_parent,
692 LttField *field, void *data)
693{
694 size_t size = 0;
695 guint i;
696 LttType *type;
697
698 g_assert(field->fixed_root != FIELD_UNKNOWN);
699 g_assert(field->fixed_parent != FIELD_UNKNOWN);
700 g_assert(field->fixed_size != FIELD_UNKNOWN);
701
702 field->offset_root = offset_root;
703 field->offset_parent = offset_parent;
704
705 type = field->field_type;
706
707 switch(type->type_class) {
708 case LTT_INT:
709 case LTT_UINT:
710 case LTT_FLOAT:
711 case LTT_ENUM:
712 case LTT_POINTER:
713 case LTT_LONG:
714 case LTT_ULONG:
715 case LTT_SIZE_T:
716 case LTT_SSIZE_T:
717 case LTT_OFF_T:
718 g_assert(field->fixed_size == FIELD_FIXED);
719 size = field->field_size;
720 break;
721 case LTT_SEQUENCE:
722 {
723 gint seqnum = ltt_get_uint(LTT_GET_BO(tf),
724 field->sequ_number_size,
725 data + offset_root);
726
727 if(field->child[0]->fixed_size == FIELD_FIXED) {
728 size = field->sequ_number_size +
729 (seqnum * get_field_type_size(tf, event_type,
730 offset_root, offset_parent,
731 field->child[0], data));
732 } else {
733 size += field->sequ_number_size;
734 for(i=0;i<seqnum;i++) {
735 size_t child_size;
736 child_size = get_field_type_size(tf, event_type,
737 offset_root, offset_parent,
738 field->child[0], data);
739 offset_root += child_size;
740 offset_parent += child_size;
741 size += child_size;
742 }
743 }
744 field->field_size = size;
745 }
746 break;
747 case LTT_STRING:
748 size = strlen((char*)(data+offset_root)) + 1;// length + \0
749 field->field_size = size;
750 break;
751 case LTT_ARRAY:
752 if(field->fixed_size == FIELD_FIXED)
753 size = field->field_size;
754 else {
755 for(i=0;i<field->field_type->element_number;i++) {
756 size_t child_size;
757 child_size = get_field_type_size(tf, event_type,
758 offset_root, offset_parent,
759 field->child[0], data);
760 offset_root += child_size;
761 offset_parent += child_size;
762 size += child_size;
763 }
764 field->field_size = size;
765 }
766 break;
767 case LTT_STRUCT:
768 if(field->fixed_size == FIELD_FIXED)
769 size = field->field_size;
770 else {
771 size_t current_root_offset = offset_root;
772 size_t current_offset = 0;
773 size_t child_size = 0;
774 for(i=0;i<type->element_number;i++) {
775 child_size = get_field_type_size(tf,
776 event_type, current_root_offset, current_offset,
777 field->child[i], data);
778 current_offset += child_size;
779 current_root_offset += child_size;
780
781 }
782 size = current_offset;
783 field->field_size = size;
784 }
785 break;
786 case LTT_UNION:
787 if(field->fixed_size == FIELD_FIXED)
788 size = field->field_size;
789 else {
790 size_t current_root_offset = field->offset_root;
791 size_t current_offset = 0;
792 for(i=0;i<type->element_number;i++) {
793 size = get_field_type_size(tf, event_type,
794 current_root_offset, current_offset,
795 field->child[i], data);
796 size = max(size, field->child[i]->field_size);
797 }
798 field->field_size = size;
799 }
800 break;
801 }
802
803 return size;
804}
805
806
807
808
809
810/* Print the code that calculates the length of an field */
811int print_field_len(type_descriptor_t * td, FILE *fd, unsigned int tabs,
812 char *nest_type_name, char *nest_field_name, char *field_name,
813 char *output_var, char *member_var)
814{
815 /* Type name : basename */
816 char basename[PATH_MAX];
817 unsigned int basename_len = 0;
818
819 strcpy(basename, nest_type_name);
820 basename_len = strlen(basename);
821
822 /* For a named type, we use the type_name directly */
823 if(td->type_name != NULL) {
824 strncpy(basename, td->type_name, PATH_MAX);
825 basename_len = strlen(basename);
826 } else {
827 /* For a unnamed type, there must be a field name */
828 if((basename_len != 0)
829 && (basename[basename_len-1] != '_')
830 && (field_name[0] != '\0')) {
831 strncat(basename, "_", PATH_MAX - basename_len);
832 basename_len = strlen(basename);
833 }
834 strncat(basename, field_name, PATH_MAX - basename_len);
835 }
836
837 /* Field name : basefieldname */
838 char basefieldname[PATH_MAX];
839 unsigned int basefieldname_len = 0;
840
841 strcpy(basefieldname, nest_field_name);
842 basefieldname_len = strlen(basefieldname);
843
844 /* there must be a field name */
845 strncat(basefieldname, field_name, PATH_MAX - basefieldname_len);
846 basefieldname_len = strlen(basefieldname);
847
848 print_tabs(tabs, fd);
849
850 switch(td->type) {
851 case INT_FIXED:
852 case UINT_FIXED:
853 case CHAR:
854 case UCHAR:
855 case SHORT:
856 case USHORT:
857 case INT:
858 case UINT:
859 case FLOAT:
860 case POINTER:
861 case LONG:
862 case ULONG:
863 case SIZE_T:
864 case SSIZE_T:
865 case OFF_T:
866 case ENUM:
867 fprintf(fd, "/* Size of %s */", field_name);
868 print_tabs(tabs, fd);
869 fprintf(fd, "%s = sizeof(", member_var);
870 if(print_type(td, fd, tabs, basename, "")) return 1;
871 fprintf(fd, ");\n");
872 fprintf(fd, "%s += ltt_align(%s, %s);\n", output_var, member_var);
873 print_tabs(tabs, fd);
874 fprintf(fd, "%s += %s;\n", output_var, member_var);
875 break;
876 case STRING:
877 /* strings are made of bytes : no alignment. */
878 fprintf(fd, "/* Size of %s */", basefieldname);
879 print_tabs(tabs, fd);
880 fprintf(fd, "%s = strlen(%s);", member_var, basefieldname);
881 break;
882 case ARRAY:
883 fprintf(fd, "/* Size of %s */", basefieldname);
884 print_tabs(tabs, fd);
885
886 strncat(basefieldname, ".", PATH_MAX - basefieldname_len);
887 basefieldname_len = strlen(basefieldname);
888
889 if(print_field_len(((field_t*)td->fields.array[0])->type,
890 fd, tabs,
891 basename, basefieldname,
892 output_var, member_var)) return 1;
893
894 fprintf(fd, "%s = strlen(%s);", member_var, basefieldname);
895
896 fprintf(fd, "lttng_array_%s", basename);
897 fprintf(fd, " %s", field_name);
898 break;
899 case SEQUENCE:
900 fprintf(fd, "lttng_sequence_%s *", basename);
901 fprintf(fd, " %s", field_name);
902 break;
903 case STRUCT:
904 fprintf(fd, "struct lttng_%s *", basename);
905 fprintf(fd, " %s", field_name);
906 break;
907 case UNION:
908 fprintf(fd, "union lttng_%s *", basename);
909 fprintf(fd, " %s", field_name);
910 break;
911 default:
912 printf("print_type : unknown type\n");
913 return 1;
914 }
915
916 return 0;
917}
918
919
920
921
47299663 922/* Print the logging function of an event. This is the core of genevent */
923int print_event_logging_function(char *basename, event_t *event, FILE *fd)
924{
925 fprintf(fd, "static inline void trace_%s(\n", basename);
926 for(unsigned int j = 0; j < event->fields.position; j++) {
927 /* For each field, print the function argument */
928 field_t *f = (field_t*)event->fields.array[j];
929 type_descriptor_t *t = f->type;
7e97b039 930 if(print_arg(t, fd, 2, basename, f->name)) return 1;
47299663 931 if(j < event->fields.position-1) {
932 fprintf(fd, ",");
933 fprintf(fd, "\n");
934 }
935 }
936 if(event->fields.position == 0) {
937 print_tabs(2, fd);
938 fprintf(fd, "void");
939 }
940 fprintf(fd,")\n");
941 fprintf(fd, "#ifndef CONFIG_LTT\n");
942 fprintf(fd, "{\n");
943 fprintf(fd, "}\n");
944 fprintf(fd,"#else\n");
945 fprintf(fd, "{\n");
7e97b039 946 /* Print the function variables */
a67cd958 947 print_tabs(1, fd);
948 fprintf(fd, "size_t member_length;");
949 fprintf(fd, "size_t event_length = 0;");
7e97b039 950
a67cd958 951 /* Calculate event variable len + event data alignment offset.
7e97b039 952 * Assume that the padding for alignment starts at a void*
a67cd958 953 * address.
954 * This excludes the header size and alignment. */
955
956
957 for(unsigned int j = 0; j < event->fields.position; j++) {
958 /* For each field, calculate the field size. */
959 field_t *f = (field_t*)event->fields.array[j];
960 type_descriptor_t *t = f->type;
961 if(print_field_len(t, fd, 1, basename, "",
962 f->name,
963 "event_length",
964 "member_length")) return 1;
965 if(j < event->fields.position-1) {
966 fprintf(fd, ",");
967 fprintf(fd, "\n");
968 }
969 }
47299663 970
7e97b039 971 /* Take locks : make sure the trace does not vanish while we write on
972 * it. A simple preemption disabling is enough (using rcu traces). */
973
974 /* For each trace */
975
976 /* Relay reserve */
977 /* If error, increment counter and return */
978
979 /* write data */
980
981 /* commit */
982
983 /* Release locks */
2d2d14a7 984
47299663 985 fprintf(fd, "}\n");
986 fprintf(fd, "#endif //CONFIG_LTT\n\n");
987 return 0;
988}
2d2d14a7 989
990
991/* ltt-facility-name.h : main logging header.
992 * log_header */
993
994void print_log_header_head(facility_t *fac, FILE *fd)
995{
996 fprintf(fd, "#ifndef _LTT_FACILITY_%s_H_\n", fac->capname);
997 fprintf(fd, "#define _LTT_FACILITY_%s_H_\n\n", fac->capname);
47299663 998 fprintf(fd, "\n");
999 fprintf(fd, "/* Facility activation at compile time. */\n");
1000 fprintf(fd, "#ifdef CONFIG_LTT_FACILITY_%s\n\n", fac->capname);
2d2d14a7 1001}
1002
1003
1004
2d2d14a7 1005int print_log_header_types(facility_t *fac, FILE *fd)
1006{
1007 sequence_t *types = &fac->named_types.values;
1008 fprintf(fd, "/* Named types */\n");
1009 fprintf(fd, "\n");
1010
1011 for(unsigned int i = 0; i < types->position; i++) {
1012 /* For each named type, print the definition */
1013 if((print_type_declaration(types->array[i], fd,
1014 0, "", ""))) return 1;
1015 }
1016 return 0;
1017}
1018
1019int print_log_header_events(facility_t *fac, FILE *fd)
1020{
47299663 1021 sequence_t *events = &fac->events;
1022 char basename[PATH_MAX];
1023 unsigned int facname_len;
1024
1025 strncpy(basename, fac->name, PATH_MAX);
1026 facname_len = strlen(basename);
1027 strncat(basename, "_", PATH_MAX-facname_len);
1028 facname_len = strlen(basename);
1029
1030 for(unsigned int i = 0; i < events->position; i++) {
1031 event_t *event = (event_t*)events->array[i];
1032 strncpy(&basename[facname_len], event->name, PATH_MAX-facname_len);
1033
1034 /* For each event, print structure, and then logging function */
1035 fprintf(fd, "/* Event %s structures */\n",
1036 event->name);
1037 for(unsigned int j = 0; j < event->fields.position; j++) {
1038 /* For each unnamed type, print the definition */
1039 field_t *f = (field_t*)event->fields.array[j];
1040 type_descriptor_t *t = f->type;
1041 if(t->type_name == NULL)
1042 if((print_type_declaration(t, fd, 0, basename, f->name))) return 1;
1043 }
1044 fprintf(fd, "\n");
2d2d14a7 1045
47299663 1046 fprintf(fd, "/* Event %s logging function */\n",
1047 event->name);
1048
1049 if(print_event_logging_function(basename, event, fd)) return 1;
1050
1051 fprintf(fd, "\n");
1052 }
1053
2d2d14a7 1054 return 0;
1055}
1056
1057
1058void print_log_header_tail(facility_t *fac, FILE *fd)
1059{
47299663 1060 fprintf(fd, "#endif //CONFIG_LTT_FACILITY_%s\n\n", fac->capname);
2d2d14a7 1061 fprintf(fd, "#endif //_LTT_FACILITY_%s_H_\n",fac->capname);
1062}
1063
1064int print_log_header(facility_t *fac)
1065{
1066 char filename[PATH_MAX];
1067 unsigned int filename_size = 0;
1068 FILE *fd;
1069 dprintf("%s\n", fac->name);
1070
1071 strcpy(filename, "ltt-facility-");
1072 filename_size = strlen(filename);
1073
1074 strncat(filename, fac->name, PATH_MAX - filename_size);
1075 filename_size = strlen(filename);
1076
1077 strncat(filename, ".h", PATH_MAX - filename_size);
1078 filename_size = strlen(filename);
1079
1080
1081 fd = fopen(filename, "w");
1082 if(fd == NULL) {
1083 printf("Error opening file %s for writing : %s\n",
1084 filename, strerror(errno));
1085 return errno;
1086 }
1087
1088 /* Print file head */
1089 print_log_header_head(fac, fd);
1090
1091 /* print named types in declaration order */
1092 if(print_log_header_types(fac, fd)) return 1;
1093
1094 /* Print events */
1095 if(print_log_header_events(fac, fd)) return 1;
1096
1097 /* Print file tail */
1098 print_log_header_tail(fac, fd);
1099
1100
1101 fclose(fd);
1102
1103 return 0;
1104}
1105
1106
1107/* ltt-facility-id-name.h : facility id.
1108 * log_id_header */
1109int print_id_header(facility_t *fac)
1110{
1111 char filename[PATH_MAX];
1112 unsigned int filename_size = 0;
1113 FILE *fd;
1114 dprintf("%s\n", fac->name);
1115
1116 strcpy(filename, "ltt-facility-id-");
1117 filename_size = strlen(filename);
1118
1119 strncat(filename, fac->name, PATH_MAX - filename_size);
1120 filename_size = strlen(filename);
1121
1122 strncat(filename, ".h", PATH_MAX - filename_size);
1123 filename_size = strlen(filename);
1124
1125
1126 fd = fopen(filename, "w");
1127 if(fd == NULL) {
1128 printf("Error opening file %s for writing : %s\n",
1129 filename, strerror(errno));
1130 return errno;
1131 }
1132
1133 fclose(fd);
1134
1135 return 0;
1136}
1137
1138
1139/* ltt-facility-loader-name.h : facility specific loader info.
1140 * loader_header */
1141int print_loader_header(facility_t *fac)
1142{
1143 char filename[PATH_MAX];
1144 unsigned int filename_size = 0;
1145 FILE *fd;
1146 dprintf("%s\n", fac->name);
1147
1148 strcpy(filename, "ltt-facility-loader-");
1149 filename_size = strlen(filename);
1150
1151 strncat(filename, fac->name, PATH_MAX - filename_size);
1152 filename_size = strlen(filename);
1153
1154 strncat(filename, ".h", PATH_MAX - filename_size);
1155 filename_size = strlen(filename);
1156
1157
1158 fd = fopen(filename, "w");
1159 if(fd == NULL) {
1160 printf("Error opening file %s for writing : %s\n",
1161 filename, strerror(errno));
1162 return errno;
1163 }
1164
1165 fclose(fd);
1166
1167 return 0;
1168}
1169
1170/* ltt-facility-loader-name.c : generic faciilty loader
1171 * loader_c */
1172int print_loader_c(facility_t *fac)
1173{
1174 char filename[PATH_MAX];
1175 unsigned int filename_size = 0;
1176 FILE *fd;
1177 dprintf("%s\n", fac->name);
1178
1179 strcpy(filename, "ltt-facility-loader-");
1180 filename_size = strlen(filename);
1181
1182 strncat(filename, fac->name, PATH_MAX - filename_size);
1183 filename_size = strlen(filename);
1184
1185 strncat(filename, ".c", PATH_MAX - filename_size);
1186 filename_size = strlen(filename);
1187
1188
1189 fd = fopen(filename, "w");
1190 if(fd == NULL) {
1191 printf("Error opening file %s for writing : %s\n",
1192 filename, strerror(errno));
1193 return errno;
1194 }
1195
1196
1197 fclose(fd);
1198
1199 return 0;
1200}
1201
1202
1203
92d82357 1204/* open facility */
1205/* code taken from ltt_facility_open in ltt/facility.c in lttv */
1206
1207/*****************************************************************************
1208 *Function name
1209 * ltt_facility_open : open facilities
1210 *Input params
1211 * pathname : the path name of the facility
1212 *
1213 * Open the facility corresponding to the right checksum.
1214 *
1215 *returns the facility on success, NULL on error.
1216 ****************************************************************************/
1217facility_t *ltt_facility_open(char * pathname)
1218{
1219 int ret = 0;
1220 char *token;
1221 parse_file_t in;
1222 facility_t * fac = NULL;
1223 unsigned long checksum;
1224 char buffer[BUFFER_SIZE];
1225 int generated = FALSE;
1226
1227 in.buffer = &(buffer[0]);
1228 in.lineno = 0;
1229 in.error = error_callback;
1230 in.name = pathname;
1231 in.unget = 0;
1232
1233 in.fp = fopen(in.name, "r");
1234 if(in.fp == NULL) {
1235 ret = 1;
1236 goto open_error;
1237 }
1238
1239 while(1){
1240 token = getToken(&in);
1241 if(in.type == ENDFILE) break;
1242
1243 if(generated) {
1244 printf("More than one facility in the file. Only using the first one.\n");
1245 break;
1246 }
1247
1248 if(strcmp(token, "<")) in.error(&in,"not a facility file");
1249 token = getName(&in);
1250
1251 if(strcmp("facility",token) == 0) {
1252 fac = malloc(sizeof(facility_t));
1253 fac->name = NULL;
1254 fac->description = NULL;
1255 sequence_init(&(fac->events));
1256 table_init(&(fac->named_types));
1257 sequence_init(&(fac->unnamed_types));
1258
1259 parseFacility(&in, fac);
1260
1261 //check if any namedType is not defined
1262 checkNamedTypesImplemented(&fac->named_types);
1263
1264 generateChecksum(fac->name, &checksum, &fac->events);
a67cd958 1265
92d82357 1266 generated = TRUE;
1267 }
1268 else {
1269 printf("facility token was expected in file %s\n", in.name);
1270 ret = 1;
1271 goto parse_error;
1272 }
1273 }
1274
1275 parse_error:
1276 fclose(in.fp);
1277open_error:
1278
1279 if(!generated) {
1280 printf("Cannot find facility %s\n", pathname);
1281 fac = NULL;
1282 }
1283
1284 return fac;
1285}
1286
1287/* Close the facility */
1288void ltt_facility_close(facility_t *fac)
1289{
1290 free(fac->name);
1291 free(fac->capname);
1292 free(fac->description);
1293 freeEvents(&fac->events);
1294 sequence_dispose(&fac->events);
1295 freeNamedType(&fac->named_types);
1296 table_dispose(&fac->named_types);
1297 freeTypes(&fac->unnamed_types);
1298 sequence_dispose(&fac->unnamed_types);
1299 free(fac);
1300}
1301
1302
1303/* Show help */
1304void show_help(int argc, char ** argv)
1305{
1306 printf("Genevent help : \n");
1307 printf("\n");
1308 printf("Use %s name.xml\n", argv[0]);
1309 printf("to create :\n");
1310 printf("ltt-facility-name.h\n");
1311 printf("ltt-facility-id-name.h\n");
1312 printf("ltt-facility-loader-name.h\n");
1313 printf("ltt-facility-loader-name.c\n");
1314 printf("In the current directory.\n");
1315 printf("\n");
1316}
1317
1318/* Parse program arguments */
1319/* Return values :
1320 * 0 : continue program
1321 * -1 : stop program, return 0
1322 * > 0 : stop program, return value as exit.
1323 */
1324int check_args(int argc, char **argv)
1325{
1326 if(argc < 2) {
1327 printf("Not enough arguments\n");
1328 show_help(argc, argv);
1329 return EINVAL;
1330 }
1331
1332 if(strcmp(argv[1], "-h") == 0) {
1333 show_help(argc, argv);
1334 return -1;
1335 }
1336
1337 return 0;
1338}
1339
1340int main(int argc, char **argv)
1341{
1342 int err = 0;
1343 facility_t *fac;
1344
1345 err = check_args(argc, argv);
1346 if(err > 0) return err;
1347 else if(err < 0) return 0;
1348
1349 /* open the facility */
1350 fac = ltt_facility_open(argv[1]);
1351 if(fac == NULL) {
1352 printf("Error opening file %s for reading : %s\n",
1353 argv[1], strerror(errno));
1354 return errno;
1355 }
1356
1357 /* generate the output C files */
1358
1359
2d2d14a7 1360 /* ltt-facility-name.h : main logging header.
1361 * log_header */
1362 err = print_log_header(fac);
1363 if(err) return err;
92d82357 1364
2d2d14a7 1365 /* ltt-facility-id-name.h : facility id.
1366 * log_id_header */
1367 err = print_id_header(fac);
1368 if(err) return err;
92d82357 1369
2d2d14a7 1370 /* ltt-facility-loader-name.h : facility specific loader info.
1371 * loader_header */
1372 err = print_loader_header(fac);
1373 if(err) return err;
1374
1375 /* ltt-facility-loader-name.c : generic faciilty loader
1376 * loader_c */
1377 err = print_loader_c(fac);
1378 if(err) return err;
92d82357 1379
1380 /* close the facility */
1381 ltt_facility_close(fac);
1382
1383 return 0;
1384}
1385
1386
This page took 0.074157 seconds and 4 git commands to generate.