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 |
89 | void 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 |
96 | void 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 |
104 | int print_check(int fd); |
105 | |
106 | |
2d2d14a7 |
107 | /* print type. |
108 | * |
109 | * Copied from construct_types_and_fields in LTTV facility.c */ |
110 | |
111 | int 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 */ |
208 | int 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 | |
a3e6ce64 |
328 | /* Does the type has a fixed size ? (as know from the compiler) |
329 | * |
330 | * 1 : fixed size |
331 | * 0 : variable length |
332 | */ |
333 | int has_type_fixed_size(type_descriptor_t *td) |
334 | { |
335 | switch(td->type) { |
336 | case INT_FIXED: |
337 | case UINT_FIXED: |
338 | case CHAR: |
339 | case UCHAR: |
340 | case SHORT: |
341 | case USHORT: |
342 | case INT: |
343 | case UINT: |
344 | case FLOAT: |
345 | case POINTER: |
346 | case LONG: |
347 | case ULONG: |
348 | case SIZE_T: |
349 | case SSIZE_T: |
350 | case OFF_T: |
351 | case ENUM: |
352 | case UNION: /* The union must have fixed size children. Must be checked by |
353 | the parser */ |
354 | return 1; |
355 | break; |
356 | case STRING: |
357 | case SEQUENCE: |
358 | return 0; |
359 | break; |
360 | case STRUCT: |
361 | { |
362 | int has_type_fixed = 0; |
363 | for(unsigned int i=0;i<td->fields.position;i++){ |
364 | field_t *field = (field_t*)(td->fields.array[i]); |
365 | type_descriptor_t *type = field->type; |
366 | |
367 | has_type_fixed = has_type_fixed_size(type); |
368 | if(!has_type_fixed) return 0; |
369 | } |
370 | return 1; |
371 | } |
372 | break; |
373 | case ARRAY: |
374 | assert(td->size >= 0); |
375 | return has_type_fixed(((field_t*)td->fields.array[0])->type); |
376 | break; |
377 | } |
378 | } |
379 | |
380 | |
381 | |
382 | |
383 | |
2d2d14a7 |
384 | /* print type declaration. |
385 | * |
386 | * Copied from construct_types_and_fields in LTTV facility.c */ |
387 | |
388 | int print_type_declaration(type_descriptor_t * td, FILE *fd, unsigned int tabs, |
389 | char *nest_name, char *field_name) |
390 | { |
391 | char basename[PATH_MAX]; |
392 | unsigned int basename_len = 0; |
393 | |
7b175edc |
394 | strncpy(basename, nest_name, PATH_MAX); |
2d2d14a7 |
395 | basename_len = strlen(basename); |
396 | |
397 | /* For a named type, we use the type_name directly */ |
398 | if(td->type_name != NULL) { |
399 | strncpy(basename, td->type_name, PATH_MAX); |
400 | basename_len = strlen(basename); |
401 | } else { |
7b175edc |
402 | /* For a unnamed type, there must be a field name, except for |
403 | * the array. */ |
404 | if((basename_len != 0) |
405 | && (basename[basename_len-1] != '_' |
406 | && (field_name[0] != '\0'))) { |
2d2d14a7 |
407 | strncat(basename, "_", PATH_MAX - basename_len); |
408 | basename_len = strlen(basename); |
409 | } |
410 | strncat(basename, field_name, PATH_MAX - basename_len); |
2d2d14a7 |
411 | } |
412 | |
413 | switch(td->type) { |
414 | case ENUM: |
415 | fprintf(fd, "enum lttng_%s", basename); |
416 | fprintf(fd, " {\n"); |
417 | for(unsigned int i=0;i<td->labels.position;i++){ |
418 | print_tabs(1, fd); |
419 | fprintf(fd, "LTTNG_%s", ((char*)(td->labels.array[i]))); |
420 | fprintf(fd, ",\n"); |
421 | } |
422 | fprintf(fd, "};\n"); |
423 | fprintf(fd, "\n"); |
424 | break; |
425 | |
426 | case ARRAY: |
7b175edc |
427 | dprintf("%s\n", basename); |
2d2d14a7 |
428 | assert(td->size >= 0); |
a67cd958 |
429 | if(((field_t*)td->fields.array[0])->type->type_name == NULL) { |
2d2d14a7 |
430 | /* Not a named nested type : we must print its declaration first */ |
a67cd958 |
431 | if(print_type_declaration(((field_t*)td->fields.array[0])->type, |
2d2d14a7 |
432 | fd, 0, basename, "")) return 1; |
433 | } |
434 | fprintf(fd, "#define LTTNG_ARRAY_SIZE_%s %llu\n", basename, |
435 | td->size); |
7e97b039 |
436 | fprintf(fd, "typedef "); |
a67cd958 |
437 | if(print_type(((field_t*)td->fields.array[0])->type, |
438 | fd, tabs, basename, "")) return 1; |
2d2d14a7 |
439 | fprintf(fd, " lttng_array_%s[LTTNG_ARRAY_SIZE_%s];\n", basename, |
440 | basename); |
441 | fprintf(fd, "\n"); |
442 | break; |
443 | case SEQUENCE: |
a67cd958 |
444 | /* We assume that the sequence length type does not need to be declared. |
445 | */ |
446 | if(((field_t*)td->fields.array[1])->type->type_name == NULL) { |
2d2d14a7 |
447 | /* Not a named nested type : we must print its declaration first */ |
a67cd958 |
448 | if(print_type_declaration(((field_t*)td->fields.array[1])->type, |
2d2d14a7 |
449 | fd, 0, basename, "")) return 1; |
450 | } |
451 | fprintf(fd, "typedef struct lttng_sequence_%s lttng_sequence_%s;\n", |
452 | basename, |
453 | basename); |
454 | fprintf(fd, "struct lttng_sequence_%s", basename); |
455 | fprintf(fd, " {\n"); |
456 | print_tabs(1, fd); |
a3e6ce64 |
457 | if(print_type(((field_t*)td->fields.array[0])->type, |
458 | fd, tabs, basename, "")) return 1; |
459 | fprintf(fd, "len;\n"); |
2d2d14a7 |
460 | print_tabs(1, fd); |
a67cd958 |
461 | if(print_type(((field_t*)td->fields.array[1])->type, |
462 | fd, tabs, basename, "")) return 1; |
2d2d14a7 |
463 | fprintf(fd, " *array;\n"); |
464 | fprintf(fd, "};\n"); |
465 | fprintf(fd, "\n"); |
466 | break; |
467 | |
468 | case STRUCT: |
469 | for(unsigned int i=0;i<td->fields.position;i++){ |
470 | field_t *field = (field_t*)(td->fields.array[i]); |
471 | type_descriptor_t *type = field->type; |
472 | if(type->type_name == NULL) { |
473 | /* Not a named nested type : we must print its declaration first */ |
474 | if(print_type_declaration(type, |
475 | fd, 0, basename, field->name)) return 1; |
476 | } |
477 | } |
478 | fprintf(fd, "struct lttng_%s", basename); |
479 | fprintf(fd, " {\n"); |
480 | for(unsigned int i=0;i<td->fields.position;i++){ |
481 | field_t *field = (field_t*)(td->fields.array[i]); |
482 | type_descriptor_t *type = field->type; |
483 | print_tabs(1, fd); |
47299663 |
484 | if(print_type(type, fd, tabs, basename, field->name)) return 1; |
2d2d14a7 |
485 | fprintf(fd, " "); |
486 | fprintf(fd, "%s", field->name); |
487 | fprintf(fd, ";\n"); |
488 | } |
489 | fprintf(fd, "};\n"); |
490 | fprintf(fd, "\n"); |
491 | break; |
492 | case UNION: |
493 | /* TODO : Do not allow variable length fields in a union */ |
494 | for(unsigned int i=0;i<td->fields.position;i++){ |
495 | field_t *field = (field_t*)(td->fields.array[i]); |
496 | type_descriptor_t *type = field->type; |
497 | if(type->type_name == NULL) { |
498 | /* Not a named nested type : we must print its declaration first */ |
47299663 |
499 | if(print_type_declaration(type, |
500 | fd, 0, basename, field->name)) return 1; |
2d2d14a7 |
501 | } |
502 | } |
503 | fprintf(fd, "union lttng_%s", basename); |
504 | fprintf(fd, " {\n"); |
505 | for(unsigned i=0;i<td->fields.position;i++){ |
506 | field_t *field = (field_t*)(td->fields.array[i]); |
507 | type_descriptor_t *type = field->type; |
508 | print_tabs(1, fd); |
47299663 |
509 | if(print_type(type, fd, tabs, basename, field->name)) return 1; |
2d2d14a7 |
510 | fprintf(fd, " "); |
511 | fprintf(fd, "%s", field->name); |
512 | fprintf(fd, ";\n"); |
513 | } |
514 | fprintf(fd, "};\n"); |
515 | fprintf(fd, "\n"); |
516 | break; |
517 | default: |
518 | dprintf("print_type_declaration : unknown type or nothing to declare.\n"); |
519 | break; |
520 | } |
521 | |
522 | return 0; |
523 | } |
524 | |
a67cd958 |
525 | |
a3e6ce64 |
526 | /* print type alignment. |
527 | * |
528 | * Copied from construct_types_and_fields in LTTV facility.c |
529 | * |
530 | * basename is the name which identifies the type (along with a prefix |
531 | * (possibly)). */ |
a67cd958 |
532 | |
a3e6ce64 |
533 | int print_type_alignment(type_descriptor_t * td, FILE *fd, unsigned int tabs, |
534 | char *nest_name, char *field_name) |
a67cd958 |
535 | { |
a3e6ce64 |
536 | char basename[PATH_MAX]; |
537 | unsigned int basename_len = 0; |
538 | |
539 | strncpy(basename, nest_name, PATH_MAX); |
540 | basename_len = strlen(basename); |
541 | |
542 | /* For a named type, we use the type_name directly */ |
543 | if(td->type_name != NULL) { |
544 | strncpy(basename, td->type_name, PATH_MAX); |
545 | basename_len = strlen(basename); |
a67cd958 |
546 | } else { |
a3e6ce64 |
547 | /* For a unnamed type, there must be a field name, except for |
548 | * the array. */ |
549 | if((basename_len != 0) |
550 | && (basename[basename_len-1] != '_' |
551 | && (field_name[0] != '\0'))) { |
552 | strncat(basename, "_", PATH_MAX - basename_len); |
553 | basename_len = strlen(basename); |
a67cd958 |
554 | } |
a3e6ce64 |
555 | strncat(basename, field_name, PATH_MAX - basename_len); |
a67cd958 |
556 | } |
a3e6ce64 |
557 | |
558 | switch(td->type) { |
a67cd958 |
559 | case INT_FIXED: |
560 | case UINT_FIXED: |
a67cd958 |
561 | case CHAR: |
562 | case UCHAR: |
563 | case SHORT: |
564 | case USHORT: |
a3e6ce64 |
565 | case INT: |
566 | case UINT: |
567 | case FLOAT: |
568 | case POINTER: |
569 | case LONG: |
570 | case ULONG: |
571 | case SIZE_T: |
572 | case SSIZE_T: |
573 | case OFF_T: |
574 | case ENUM: |
575 | fprintf(fd, "sizeof("); |
576 | if(print_type(td->type, |
577 | fd, 0, basename, "")) return 1; |
578 | fprintf(fd, ")"); |
579 | break; |
580 | case STRING: |
581 | fprintf(fd, "sizeof(char)"); |
582 | break; |
583 | case SEQUENCE: |
584 | fprintf(fd, "lttng_get_alignment_sequence_%s(&obj->%s)", basename, |
585 | field_name); |
586 | break; |
587 | case STRUCT: |
588 | fprintf(fd, "lttng_get_alignment_struct_%s(&obj->%s)", basename, |
589 | field_name); |
590 | break; |
591 | case UNION: |
592 | fprintf(fd, "lttng_get_alignment_union_%s(&obj->%s)", basename, |
593 | field_name); |
594 | break; |
595 | case ARRAY: |
596 | fprintf(fd, "lttng_get_alignment_array_%s(obj->%s)", basename, |
597 | field_name); |
598 | break; |
599 | } |
a67cd958 |
600 | |
a3e6ce64 |
601 | return 0; |
a67cd958 |
602 | } |
603 | |
a3e6ce64 |
604 | /* print type write. |
605 | * |
606 | * Copied from construct_types_and_fields in LTTV facility.c |
607 | * |
608 | * basename is the name which identifies the type (along with a prefix |
609 | * (possibly)). */ |
a67cd958 |
610 | |
a3e6ce64 |
611 | int print_type_write(type_descriptor_t * td, FILE *fd, unsigned int tabs, |
612 | char *nest_name, char *field_name) |
a67cd958 |
613 | { |
a67cd958 |
614 | char basename[PATH_MAX]; |
615 | unsigned int basename_len = 0; |
a3e6ce64 |
616 | |
617 | strncpy(basename, nest_name, PATH_MAX); |
a67cd958 |
618 | basename_len = strlen(basename); |
619 | |
620 | /* For a named type, we use the type_name directly */ |
621 | if(td->type_name != NULL) { |
622 | strncpy(basename, td->type_name, PATH_MAX); |
623 | basename_len = strlen(basename); |
624 | } else { |
a3e6ce64 |
625 | /* For a unnamed type, there must be a field name, except for |
626 | * the array. */ |
a67cd958 |
627 | if((basename_len != 0) |
a3e6ce64 |
628 | && (basename[basename_len-1] != '_' |
629 | && (field_name[0] != '\0'))) { |
a67cd958 |
630 | strncat(basename, "_", PATH_MAX - basename_len); |
631 | basename_len = strlen(basename); |
632 | } |
633 | strncat(basename, field_name, PATH_MAX - basename_len); |
634 | } |
635 | |
a67cd958 |
636 | switch(td->type) { |
637 | case INT_FIXED: |
638 | case UINT_FIXED: |
639 | case CHAR: |
640 | case UCHAR: |
641 | case SHORT: |
642 | case USHORT: |
643 | case INT: |
644 | case UINT: |
645 | case FLOAT: |
646 | case POINTER: |
647 | case LONG: |
648 | case ULONG: |
649 | case SIZE_T: |
650 | case SSIZE_T: |
651 | case OFF_T: |
652 | case ENUM: |
a67cd958 |
653 | print_tabs(tabs, fd); |
a3e6ce64 |
654 | fprintf(fd, "size = "); |
655 | fprintf(fd, "sizeof("); |
656 | if(print_type(td->type, |
657 | fd, 0, basename, "")) return 1; |
a67cd958 |
658 | fprintf(fd, ");\n"); |
a67cd958 |
659 | print_tabs(tabs, fd); |
a3e6ce64 |
660 | fprintf(fd, "size += ltt_align(*to+*len, size) + size;"); |
661 | print_tabs(tabs, fd); |
662 | fprintf(fd, "*len += size;"); |
a67cd958 |
663 | break; |
664 | case STRING: |
a67cd958 |
665 | print_tabs(tabs, fd); |
a3e6ce64 |
666 | fprintf(fd, "lttng_write_string_%s(buffer, to_base, to, from, len, obj->%s);\n"); |
667 | break; |
668 | case SEQUENCE: |
669 | print_tabs(tabs, fd); |
670 | fprintf(fd, "lttng_write_%s(buffer, to_base, to, from, len, obj->%s)", basename, |
671 | field_name); |
672 | break; |
673 | case STRUCT: |
674 | print_tabs(tabs, fd); |
675 | fprintf(fd, "lttng_write_struct_%s(buffer, to_base, to, from, len, obj->%s)", basename, |
676 | field_name); |
677 | break; |
678 | case UNION: |
679 | print_tabs(tabs, fd); |
680 | fprintf(fd, "lttng_write_union_%s(buffer, to_base, to, from, len, obj->%s)", basename, |
681 | field_name); |
a67cd958 |
682 | break; |
683 | case ARRAY: |
a67cd958 |
684 | print_tabs(tabs, fd); |
a3e6ce64 |
685 | fprintf(fd, "lttng_write_array_%s(buffer, to_base, to, from, len, obj->%s)", basename, |
686 | field_name); |
687 | break; |
688 | } |
a67cd958 |
689 | |
a3e6ce64 |
690 | return 0; |
691 | } |
a67cd958 |
692 | |
a67cd958 |
693 | |
a67cd958 |
694 | |
a3e6ce64 |
695 | /* print type alignment function. |
696 | * |
697 | * Copied from construct_types_and_fields in LTTV facility.c |
698 | * |
699 | * basename is the name which identifies the type (along with a prefix |
700 | * (possibly)). */ |
701 | |
702 | int print_type_alignment_fct(type_descriptor_t * td, FILE *fd, |
703 | unsigned int tabs, |
704 | char *nest_name, char *field_name) |
705 | { |
706 | char basename[PATH_MAX]; |
707 | unsigned int basename_len = 0; |
708 | |
709 | strncpy(basename, nest_name, PATH_MAX); |
710 | basename_len = strlen(basename); |
711 | |
712 | /* For a named type, we use the type_name directly */ |
713 | if(td->type_name != NULL) { |
714 | strncpy(basename, td->type_name, PATH_MAX); |
715 | basename_len = strlen(basename); |
716 | } else { |
717 | /* For a unnamed type, there must be a field name, except for |
718 | * the array. */ |
719 | if((basename_len != 0) |
720 | && (basename[basename_len-1] != '_' |
721 | && (field_name[0] != '\0'))) { |
722 | strncat(basename, "_", PATH_MAX - basename_len); |
723 | basename_len = strlen(basename); |
724 | } |
725 | strncat(basename, field_name, PATH_MAX - basename_len); |
726 | } |
727 | |
728 | switch(td->type) { |
729 | case SEQUENCE: |
730 | /* Function header */ |
731 | fprintf(fd, "static inline size_t lttng_get_alignment_sequence_%s(\n", |
732 | basename); |
733 | print_tabs(2, fd); |
734 | if(print_type(td->type, fd, 0, basename, "")) return 1; |
735 | fprintf(fd, " *obj)\n"); |
736 | fprintf(fd, "{\n"); |
737 | print_tabs(1, fd); |
738 | fprintf(fd, "size_t align=0, localign;"); |
739 | fprintf(fd, "\n"); |
740 | print_tabs(1, fd); |
741 | fprintf(fd, "localign = "); |
742 | if(print_type_alignment(((field_t*)td->fields.array[0])->type, |
743 | fd, 0, basename, field->name)) return 1; |
744 | fprintf(fd, ";\n"); |
745 | print_tabs(1, fd); |
746 | fprintf(fd, "align = max(align, localign);\n"); |
747 | fprintf(fd, "\n"); |
748 | print_tabs(1, fd); |
749 | fprintf(fd, "localign = "); |
750 | if(print_type_alignment(((field_t*)td->fields.array[1])->type, |
751 | fd, 0, basename, field->name)) return 1; |
752 | fprintf(fd, ";\n"); |
753 | print_tabs(1, fd); |
754 | fprintf(fd, "align = max(align, localign);\n"); |
755 | fprintf(fd, "\n"); |
756 | print_tabs(1, fd); |
757 | fprintf(fd, "return align;\n"); |
758 | break; |
759 | case STRUCT: |
760 | /* Function header */ |
761 | fprintf(fd, "static inline size_t lttng_get_alignment_struct_%s(\n", |
762 | basename); |
763 | print_tabs(2, fd); |
764 | if(print_type(td->type, fd, 0, basename, "")) return 1; |
765 | fprintf(fd, " *obj)\n"); |
766 | fprintf(fd, "{\n"); |
767 | print_tabs(1, fd); |
768 | fprintf(fd, "size_t align=0, localign;"); |
769 | fprintf(fd, "\n"); |
770 | for(unsigned int i=0;i<td->fields.position;i++){ |
771 | field_t *field = (field_t*)(td->fields.array[i]); |
772 | type_descriptor_t *type = field->type; |
773 | print_tabs(1, fd); |
774 | fprintf(fd, "localign = "); |
775 | if(print_type_alignment(type, fd, 0, basename, field->name)) return 1; |
776 | fprintf(fd, ";\n"); |
777 | print_tabs(1, fd); |
778 | fprintf(fd, "align = max(align, localign);\n"); |
779 | fprintf(fd, "\n"); |
780 | } |
781 | print_tabs(1, fd); |
782 | fprintf(fd, "return align;\n"); |
783 | |
a67cd958 |
784 | break; |
a3e6ce64 |
785 | case UNION: |
786 | /* Function header */ |
787 | fprintf(fd, "static inline size_t lttng_get_alignment_union_%s(\n", |
788 | basename); |
789 | print_tabs(2, fd); |
790 | if(print_type(td->type, fd, 0, basename, "")) return 1; |
791 | fprintf(fd, " *obj)\n"); |
792 | fprintf(fd, "{\n"); |
793 | print_tabs(1, fd); |
794 | fprintf(fd, "size_t align=0, localign;"); |
795 | fprintf(fd, "\n"); |
796 | for(unsigned int i=0;i<td->fields.position;i++){ |
797 | field_t *field = (field_t*)(td->fields.array[i]); |
798 | type_descriptor_t *type = field->type; |
799 | print_tabs(1, fd); |
800 | fprintf(fd, "localign = "); |
801 | if(print_type_alignment(type, fd, 0, basename, field->name)) return 1; |
802 | fprintf(fd, ";\n"); |
803 | print_tabs(1, fd); |
804 | fprintf(fd, "align = max(align, localign);\n"); |
805 | fprintf(fd, "\n"); |
806 | } |
807 | print_tabs(1, fd); |
808 | fprintf(fd, "return align;\n"); |
809 | |
810 | break; |
811 | case ARRAY: |
812 | /* Function header */ |
813 | fprintf(fd, "static inline size_t lttng_get_alignment_array_%s(\n", |
814 | basename); |
815 | print_tabs(2, fd); |
816 | if(print_type(td->type, fd, 0, basename, "")) return 1; |
817 | fprintf(fd, " obj)\n"); |
818 | fprintf(fd, "{\n"); |
819 | print_tabs(1, fd); |
820 | fprintf(fd, "return \n"); |
821 | if(print_type_alignment(((field_t*)td->fields.array[0])->type, |
822 | fd, 0, basename, field->name)) return 1; |
823 | fprintf(fd, ";\n"); |
824 | break; |
825 | default: |
826 | printf("print_type_alignment_fct : type has no alignment function.\n"); |
827 | break; |
828 | } |
829 | |
830 | |
831 | /* Function footer */ |
832 | fprintf(fd, "}\n"); |
833 | fprintf(fd, "\n"); |
834 | |
835 | } |
836 | |
837 | /* print type write function. |
838 | * |
839 | * Copied from construct_types_and_fields in LTTV facility.c |
840 | * |
841 | * basename is the name which identifies the type (along with a prefix |
842 | * (possibly)). */ |
843 | |
844 | int print_type_write_fct(type_descriptor_t * td, FILE *fd, unsigned int tabs, |
845 | char *nest_name, char *field_name) |
846 | { |
847 | char basename[PATH_MAX]; |
848 | unsigned int basename_len = 0; |
849 | |
850 | strncpy(basename, nest_name, PATH_MAX); |
851 | basename_len = strlen(basename); |
852 | |
853 | /* For a named type, we use the type_name directly */ |
854 | if(td->type_name != NULL) { |
855 | strncpy(basename, td->type_name, PATH_MAX); |
856 | basename_len = strlen(basename); |
857 | } else { |
858 | /* For a unnamed type, there must be a field name, except for |
859 | * the array. */ |
860 | if((basename_len != 0) |
861 | && (basename[basename_len-1] != '_' |
862 | && (field_name[0] != '\0'))) { |
863 | strncat(basename, "_", PATH_MAX - basename_len); |
864 | basename_len = strlen(basename); |
865 | } |
866 | strncat(basename, field_name, PATH_MAX - basename_len); |
867 | } |
868 | |
869 | /* Print header */ |
870 | switch(td->type) { |
a67cd958 |
871 | case SEQUENCE: |
a3e6ce64 |
872 | fprintf(fd, "static inline size_t lttng_get_alignment_sequence_%s(\n", |
873 | basename); |
874 | |
875 | fprintf(fd, "lttng_get_alignment_sequence_%s(&obj->%s)", basename, |
876 | field_name); |
a67cd958 |
877 | break; |
a3e6ce64 |
878 | case STRUCT: |
879 | fprintf(fd, "lttng_get_alignment_struct_%s(&obj->%s)", basename, |
880 | field_name); |
a67cd958 |
881 | break; |
a3e6ce64 |
882 | case UNION: |
883 | fprintf(fd, "lttng_get_alignment_union_%s(&obj->%s)", basename, |
884 | field_name); |
885 | break; |
886 | case ARRAY: |
887 | fprintf(fd, "lttng_get_alignment_array_%s(obj->%s)", basename, |
888 | field_name); |
889 | break; |
890 | default: |
891 | printf("print_type_write_fct : type has no write function.\n"); |
a67cd958 |
892 | break; |
a67cd958 |
893 | } |
894 | |
a3e6ce64 |
895 | print_tabs(2, fd); |
896 | fprintf(fd, "void *buffer,\n"); |
897 | print_tabs(2, fd); |
898 | fprintf(fd, "size_t *to_base,\n"); |
899 | print_tabs(2, fd); |
900 | fprintf(fd, "size_t *to,\n"); |
901 | print_tabs(2, fd); |
902 | fprintf(fd, "void **from,\n"); |
903 | print_tabs(2, fd); |
904 | fprintf(fd, "size_t *len,\n"); |
905 | print_tabs(2, fd); |
906 | if(print_type(td->type, fd, 0, basename, "")) return 1; |
907 | |
908 | switch(td->type) { |
909 | case SEQUENCE: |
910 | fprintf(fd, " *obj)\n"); |
911 | break; |
912 | case STRUCT: |
913 | fprintf(fd, " *obj)\n"); |
914 | break; |
915 | case UNION: |
916 | fprintf(fd, " *obj)\n"); |
917 | break; |
918 | case ARRAY: |
919 | fprintf(fd, " obj)\n"); |
920 | break; |
921 | default: |
922 | printf("print_type_write_fct : type has no write function.\n"); |
923 | break; |
924 | } |
925 | |
926 | fprintf(fd, "{\n"); |
927 | print_tabs(1, fd); |
928 | fprintf(fd, "size_t align, size;\n"); |
929 | fprintf(fd, "\n"); |
930 | |
931 | switch(td->type) { |
932 | case SEQUENCE: |
933 | case STRING: |
934 | print_tabs(1, fd); |
935 | fprintf(fd, "/* Flush pending memcpy */\n"); |
936 | print_tabs(1, fd); |
937 | fprintf(fd, "if(*len != 0) {\n"); |
938 | print_tabs(2, fd); |
939 | fprintf(fd, "if(buffer != NULL)\n"); |
940 | print_tabs(3, fd); |
941 | fprintf(fd, "memcpy(buffer+*to_base+*to, *from, *len);\n"); |
942 | print_tabs(1, fd); |
943 | fprintf(fd, "}\n"); |
944 | print_tabs(1, fd); |
945 | fprintf(fd, "*to += *len;\n"); |
946 | print_tabs(1, fd); |
947 | fprintf(fd, "*len = 0;\n"); |
948 | fprintf(fd, "\n"); |
949 | break; |
950 | case STRUCT: |
951 | case UNION: |
952 | case ARRAY: |
953 | break; |
954 | default: |
955 | printf("print_type_write_fct : type has no write function.\n"); |
956 | break; |
957 | } |
958 | |
959 | print_tabs(1, fd); |
960 | fprintf(fd, "align = \n"); |
961 | if(print_type_alignment(td, fd, 0, basename, field->name)) return 1; |
962 | fprintf(fd, ";\n"); |
963 | fprintf(fd, "\n"); |
964 | print_tabs(1, fd); |
965 | fprintf(fd, "if(*len == 0) {\n"); |
966 | print_tabs(2, fd); |
967 | fprintf(fd, "*to += ltt_align(*to, align); /* align output */\n"); |
968 | print_tabs(1, fd); |
969 | fprintf(fd, "} else {\n"); |
970 | print_tabs(2, fd); |
971 | fprintf(fd, "*len += ltt_align(*to+*len, align); /* alignment, ok to do a memcpy of it */\n"); |
972 | print_tabs(1, fd); |
973 | fprintf(fd, "}\n"); |
974 | fprintf(fd, "\n"); |
975 | |
976 | /* First, check if the type has a fixed size. If it is the case, then the size |
977 | * to write is know by the compiler : simply use a sizeof() */ |
978 | if(has_type_fixed_size(td)) { |
979 | print_tabs(1, fd); |
980 | fprintf(fd, "/* Contains only fixed size fields : use compiler sizeof() */\n"); |
981 | fprintf(fd, "\n"); |
982 | print_tabs(1, fd); |
983 | fprintf(fd, "*len += sizeof("); |
984 | if(print_type(td, fd, 0, basename, field->name)) return 1; |
985 | fprintf(fd, ");\n"); |
986 | } else { |
987 | /* The type contains nested variable size subtypes : |
988 | * we must write field by field. */ |
989 | print_tabs(1, fd); |
990 | fprintf(fd, "/* Contains variable sized fields : must explode the structure */\n"); |
991 | fprintf(fd, "\n"); |
992 | |
993 | switch(td->type) { |
994 | case SEQUENCE: |
995 | print_tabs(1, fd); |
996 | fprintf(fd, "/* Copy members */\n"); |
997 | print_tabs(1, fd); |
998 | fprintf(fd, "size = sizeof(\n"); |
999 | if(print_type_write(((field_t*)td->fields.array[0])->type, |
1000 | fd, 1, basename, field->name)) return 1; |
1001 | fprintf(fd, ");\n"); |
1002 | print_tabs(1, fd); |
1003 | fprintf(fd, "*to += ltt_align(*to, size);\n"); |
1004 | print_tabs(1, fd); |
1005 | fprintf(fd, "if(buffer != NULL)\n"); |
1006 | print_tabs(2, fd); |
1007 | fprintf(fd, "memcpy(buffer+*to_base+*to, &obj->len, size);\n"); |
1008 | print_tabs(1, fd); |
1009 | fprintf(fd, "*to += size;\n"); |
1010 | fprintf(fd, "\n"); |
1011 | |
1012 | /* Write the child : varlen child or not ? */ |
1013 | if(has_type_fixed_size(((field_t*)td->fields.array[1])->type)) { |
1014 | /* Fixed size len child : use a multiplication of its size */ |
1015 | print_tabs(1, fd); |
1016 | fprintf(fd, "size = sizeof(\n"); |
1017 | if(print_type_write(((field_t*)td->fields.array[1])->type, |
1018 | fd, 1, basename, field->name)) return 1; |
1019 | fprintf(fd, ");\n"); |
1020 | print_tabs(1, fd); |
1021 | fprintf(fd, "*to += ltt_align(*to, size);\n"); |
1022 | print_tabs(1, fd); |
1023 | fprintf(fd, "size = obj->len * size;\n"); |
1024 | print_tabs(1, fd); |
1025 | fprintf(fd, "if(buffer != NULL)\n"); |
1026 | print_tabs(2, fd); |
1027 | fprintf(fd, "memcpy(buffer+*to_base+*to, obj->array, size);\n"); |
1028 | print_tabs(1, fd); |
1029 | fprintf(fd, "*to += size;\n"); |
1030 | fprintf(fd, "\n"); |
1031 | } else { |
1032 | print_tabs(1, fd); |
1033 | fprintf(fd, "/* Variable length child : iter. */\n"); |
1034 | print_tabs(1, fd); |
1035 | fprintf(fd, "for(unsigned int i=0; i<obj->len; i++) {\n"); |
1036 | if(print_type_write(((field_t*)td->fields.array[1])->type, |
1037 | fd, 2, basename, field->name)) return 1; |
1038 | print_tabs(1, fd); |
1039 | fprintf(fd, "}\n"); |
1040 | } |
1041 | fprintf(fd, "\n"); |
1042 | print_tabs(1, fd); |
1043 | fprintf(fd, "/* Realign the *to_base on arch size, set *to to 0 */\n"); |
1044 | print_tabs(1, fd); |
1045 | fprintf(fd, "*to = ltt_align(*to, sizeof(void *));\n"); |
1046 | print_tabs(1, fd); |
1047 | fprintf(fd, "*to_base = *to_base+*to;\n"); |
1048 | print_tabs(1, fd); |
1049 | fprintf(fd, "*to = 0;\n"); |
1050 | fprintf(fd, "\n"); |
1051 | fprintf(fd, "/* Put source *from just after the C sequence */\n"); |
1052 | print_tabs(1, fd); |
1053 | fprintf(fd, "*from = obj+1;\n"); |
1054 | break; |
1055 | case STRING: |
1056 | fprintf(fd, "size = strlen(obj);\n"); |
1057 | print_tabs(1, fd); |
1058 | fprintf(fd, "if(buffer != NULL)\n"); |
1059 | print_tabs(2, fd); |
1060 | fprintf(fd, "memcpy(buffer+*to_base+*to, obj, size);\n"); |
1061 | print_tabs(1, fd); |
1062 | fprintf(fd, "*to += size;\n"); |
1063 | fprintf(fd, "\n"); |
1064 | print_tabs(1, fd); |
1065 | fprintf(fd, "/* Realign the *to_base on arch size, set *to to 0 */\n"); |
1066 | print_tabs(1, fd); |
1067 | fprintf(fd, "*to = ltt_align(*to, sizeof(void *));\n"); |
1068 | print_tabs(1, fd); |
1069 | fprintf(fd, "*to_base = *to_base+*to;\n"); |
1070 | print_tabs(1, fd); |
1071 | fprintf(fd, "*to = 0;\n"); |
1072 | fprintf(fd, "\n"); |
1073 | fprintf(fd, "/* Put source *from just after the C sequence */\n"); |
1074 | print_tabs(1, fd); |
1075 | fprintf(fd, "*from = obj+1;\n"); |
1076 | break; |
1077 | case STRUCT: |
1078 | for(unsigned int i=0;i<td->fields.position;i++){ |
1079 | field_t *field = (field_t*)(td->fields.array[i]); |
1080 | type_descriptor_t *type = field->type; |
1081 | if(print_type_write(type, |
1082 | fd, 1, basename, field->name)) return 1; |
1083 | fprintf(fd, "\n"); |
1084 | } |
1085 | break; |
1086 | case UNION: |
1087 | printf("ERROR : A union CANNOT contain a variable size child.\n"); |
1088 | return 1; |
1089 | break; |
1090 | case ARRAY: |
1091 | /* Write the child : varlen child or not ? */ |
1092 | if(has_type_fixed_size(((field_t*)td->fields.array[0])->type)) { |
1093 | /* Error : if an array has a variable size, then its child must also |
1094 | * have a variable size. */ |
1095 | assert(0); |
1096 | } else { |
1097 | print_tabs(1, fd); |
1098 | fprintf(fd, "/* Variable length child : iter. */\n"); |
1099 | print_tabs(1, fd); |
1100 | fprintf(fd, "for(unsigned int i=0; i<LTTNG_ARRAY_SIZE_%s; i++) {\n", basename); |
1101 | if(print_type_write(((field_t*)td->fields.array[1])->type, |
1102 | fd, 2, basename, field->name)) return 1; |
1103 | print_tabs(1, fd); |
1104 | fprintf(fd, "}\n"); |
1105 | } |
1106 | break; |
1107 | default: |
1108 | printf("print_type_write_fct : type has no write function.\n"); |
1109 | break; |
1110 | } |
1111 | |
1112 | |
1113 | } |
1114 | |
1115 | |
1116 | /* Function footer */ |
1117 | fprintf(fd, "}\n"); |
1118 | fprintf(fd, "\n"); |
a67cd958 |
1119 | return 0; |
1120 | } |
1121 | |
1122 | |
1123 | |
47299663 |
1124 | /* Print the logging function of an event. This is the core of genevent */ |
a3e6ce64 |
1125 | int print_event_logging_function(char *basename, facility_t *fac, |
1126 | event_t *event, FILE *fd) |
47299663 |
1127 | { |
1128 | fprintf(fd, "static inline void trace_%s(\n", basename); |
1129 | for(unsigned int j = 0; j < event->fields.position; j++) { |
1130 | /* For each field, print the function argument */ |
1131 | field_t *f = (field_t*)event->fields.array[j]; |
1132 | type_descriptor_t *t = f->type; |
7e97b039 |
1133 | if(print_arg(t, fd, 2, basename, f->name)) return 1; |
47299663 |
1134 | if(j < event->fields.position-1) { |
1135 | fprintf(fd, ","); |
1136 | fprintf(fd, "\n"); |
1137 | } |
1138 | } |
1139 | if(event->fields.position == 0) { |
1140 | print_tabs(2, fd); |
1141 | fprintf(fd, "void"); |
1142 | } |
1143 | fprintf(fd,")\n"); |
1144 | fprintf(fd, "#ifndef CONFIG_LTT\n"); |
1145 | fprintf(fd, "{\n"); |
1146 | fprintf(fd, "}\n"); |
1147 | fprintf(fd,"#else\n"); |
1148 | fprintf(fd, "{\n"); |
7e97b039 |
1149 | /* Print the function variables */ |
a67cd958 |
1150 | print_tabs(1, fd); |
a3e6ce64 |
1151 | fprintf(fd, "unsigned int index;\n"); |
1152 | print_tabs(1, fd); |
1153 | fprintf(fd, "struct ltt_channel_struct *channel;\n"); |
1154 | print_tabs(1, fd); |
1155 | fprintf(fd, "struct ltt_trace_struct *trace;\n"); |
1156 | print_tabs(1, fd); |
1157 | fprintf(fd, "struct rchan_buf *relayfs_buf;\n"); |
1158 | print_tabs(1, fd); |
1159 | fprintf(fd, "void *buffer = NULL;\n"); |
1160 | print_tabs(1, fd); |
1161 | fprintf(fd, "size_t to_base = 0; /* The buffer is allocated on arch_size alignment */\n"); |
1162 | print_tabs(1, fd); |
1163 | fprintf(fd, "size_t to = 0;\n"); |
1164 | print_tabs(1, fd); |
1165 | fprintf(fd, "void *from;"); |
1166 | print_tabs(1, fd); |
1167 | fprintf(fd, "size_t len = 0;\n"); |
1168 | fprintf(fd, "\n"); |
1169 | fprintf(fd, "size_t slot_size;\n"); |
1170 | fprintf(fd, "\n"); |
1171 | fprintf(fd, "cycles_t tsc;\n"); |
1172 | fprintf(fd, "\n"); |
1173 | fprintf(fd, "size_t before_hdr_pad, size_t after_hdr_pad;\n"); |
1174 | fprintf(fd, "\n"); |
7e97b039 |
1175 | |
a3e6ce64 |
1176 | print_tabs(1, fd); |
1177 | fprintf(fd, "if(ltt_traces.num_active_traces == 0) return;\n"); |
1178 | fprintf(fd, "\n"); |
1179 | |
a67cd958 |
1180 | /* Calculate event variable len + event data alignment offset. |
7e97b039 |
1181 | * Assume that the padding for alignment starts at a void* |
a67cd958 |
1182 | * address. |
1183 | * This excludes the header size and alignment. */ |
1184 | |
a3e6ce64 |
1185 | print_tabs(1, fd); |
1186 | fprintf(fd, "/* For each field, calculate the field size. */\n"); |
1187 | print_tabs(1, fd); |
1188 | fprintf(fd, "/* size = to_base + to + len */\n"); |
1189 | print_tabs(1, fd); |
1190 | fprintf(fd, "/* Assume that the padding for alignment starts at a void*\n"); |
1191 | print_tabs(1, fd); |
1192 | fprintf(fd, "/* address. */\n"); |
1193 | fprintf(fd, "\n"); |
a67cd958 |
1194 | |
a3e6ce64 |
1195 | for(unsigned int i=0;i<event->fields.position;i++){ |
1196 | field_t *field = (field_t*)(td->fields.array[i]); |
1197 | type_descriptor_t *type = field->type; |
1198 | if(print_type_write(type, |
1199 | fd, 1, basename, field->name)) return 1; |
1200 | fprintf(fd, "\n"); |
a67cd958 |
1201 | } |
47299663 |
1202 | |
7e97b039 |
1203 | /* Take locks : make sure the trace does not vanish while we write on |
1204 | * it. A simple preemption disabling is enough (using rcu traces). */ |
a3e6ce64 |
1205 | print_tabs(1, fd); |
1206 | fprintf(fd, "preempt_disable();\n"); |
1207 | print_tabs(1, fd); |
1208 | fprintf(fd, "ltt_nesting[smp_processor_id()]++;\n"); |
1209 | |
1210 | /* Get facility index */ |
1211 | |
1212 | if(event->per_tracefile) { |
1213 | print_tabs(1, fd); |
1214 | fprintf(fd, "index = tracefile_index;\n"); |
1215 | } else { |
1216 | print_tabs(1, fd); |
1217 | fprintf(fd, |
1218 | "index = ltt_get_index_from_facility(ltt_facility_%s_%X,\n"\ |
1219 | "\t\t\t\tevent_%s);\n", |
1220 | fac->name, fac->checksum, event->name); |
1221 | } |
1222 | fprintf(fd,"\n"); |
1223 | |
7e97b039 |
1224 | |
1225 | /* For each trace */ |
a3e6ce64 |
1226 | print_tabs(1, fd); |
1227 | fprintf(fd, "list_for_each_entry_rcu(trace, <t_traces.head, list) {\n"); |
1228 | print_tabs(2, fd); |
1229 | fprintf(fd, "if(!trace->active) continue;\n\n"); |
1230 | |
1231 | if(event->per_trace) { |
1232 | print_tabs(2, fd); |
1233 | fprintf(fd, "if(dest_trace != trace) continue;\n\n"); |
1234 | } |
1235 | |
1236 | print_tabs(2, fd); |
1237 | fprintf(fp, "channel = ltt_get_channel_from_index(trace, index);\n"); |
1238 | print_tabs(2, fd); |
1239 | fprintf(fd, "relayfs_buf = channel->rchan->buf[channel->rchan->buf->cpu];\n"); |
1240 | fprintf(fd, "\n"); |
1241 | |
7e97b039 |
1242 | |
1243 | /* Relay reserve */ |
a3e6ce64 |
1244 | /* If error, increment event lost counter (done by ltt_reserve_slot) and |
1245 | * return */ |
1246 | print_tabs(2, fd); |
1247 | fprintf(fd, "slot_size = 0;\n"); |
1248 | print_tabs(2, fd); |
1249 | fprintf(fd, "buffer = ltt_reserve_slot(trace, relayfs_buf, to_base + to + len, &slot_size, &tsc,\n" |
1250 | "\t\t&before_hdr_pad, &after_hdr_pad);\n"); |
1251 | /* If error, return */ |
1252 | print_tabs(2, fd); |
1253 | fprintf(fd, "if(!buffer) return;\n\n"); |
7e97b039 |
1254 | |
a3e6ce64 |
1255 | /* write data : assume stack alignment is the same as struct alignment. */ |
1256 | |
1257 | for(unsigned int i=0;i<event->fields.position;i++){ |
1258 | field_t *field = (field_t*)(td->fields.array[i]); |
1259 | type_descriptor_t *type = field->type; |
1260 | |
1261 | /* Set from */ |
1262 | print_tabs(3, fd); |
1263 | fprintf(fd, "from = %s;\n", f->name); |
1264 | |
1265 | if(print_type_write(type, |
1266 | fd, 2, basename, field->name)) return 1; |
1267 | fprintf(fd, "\n"); |
7e97b039 |
1268 | |
a3e6ce64 |
1269 | /* Don't forget to flush pending memcpy */ |
1270 | print_tabs(2, fd); |
1271 | fprintf(fd, "/* Flush pending memcpy */\n"); |
1272 | print_tabs(2, fd); |
1273 | fprintf(fd, "if(len != 0) {\n"); |
1274 | print_tabs(3, fd); |
1275 | fprintf(fd, "memcpy(buffer+to_base+to, from, len);\n"); |
1276 | print_tabs(3, fd); |
1277 | fprintf(fd, "to += len;\n"); |
1278 | //print_tabs(3, fd); |
1279 | //fprintf(fd, "from += len;\n"); |
1280 | print_tabs(3, fd); |
1281 | fprintf(fd, "len = 0;\n"); |
1282 | print_tabs(2, fd); |
1283 | fprintf(fd, "}\n"); |
1284 | fprintf(fd, "\n"); |
1285 | } |
1286 | |
1287 | |
7e97b039 |
1288 | /* commit */ |
a3e6ce64 |
1289 | print_tabs(2, fd); |
1290 | fprintf(fd, "ltt_commit_slot(relayfs_buf, buffer, slot_size);\n\n"); |
7e97b039 |
1291 | |
a3e6ce64 |
1292 | print_tabs(1, fd); |
1293 | fprintf(fd, "}\n\n"); |
1294 | |
7e97b039 |
1295 | /* Release locks */ |
a3e6ce64 |
1296 | print_tabs(1, fd); |
1297 | fprintf(fd, "ltt_nesting[smp_processor_id()]--;\n"); |
1298 | print_tabs(1, fd); |
1299 | fprintf(fd, "preempt_enable_no_resched();\n"); |
2d2d14a7 |
1300 | |
47299663 |
1301 | fprintf(fd, "}\n"); |
1302 | fprintf(fd, "#endif //CONFIG_LTT\n\n"); |
1303 | return 0; |
1304 | } |
2d2d14a7 |
1305 | |
1306 | |
1307 | /* ltt-facility-name.h : main logging header. |
1308 | * log_header */ |
1309 | |
1310 | void print_log_header_head(facility_t *fac, FILE *fd) |
1311 | { |
1312 | fprintf(fd, "#ifndef _LTT_FACILITY_%s_H_\n", fac->capname); |
1313 | fprintf(fd, "#define _LTT_FACILITY_%s_H_\n\n", fac->capname); |
47299663 |
1314 | fprintf(fd, "\n"); |
1315 | fprintf(fd, "/* Facility activation at compile time. */\n"); |
1316 | fprintf(fd, "#ifdef CONFIG_LTT_FACILITY_%s\n\n", fac->capname); |
2d2d14a7 |
1317 | } |
1318 | |
1319 | |
1320 | |
2d2d14a7 |
1321 | int print_log_header_types(facility_t *fac, FILE *fd) |
1322 | { |
1323 | sequence_t *types = &fac->named_types.values; |
1324 | fprintf(fd, "/* Named types */\n"); |
1325 | fprintf(fd, "\n"); |
1326 | |
1327 | for(unsigned int i = 0; i < types->position; i++) { |
1328 | /* For each named type, print the definition */ |
1329 | if((print_type_declaration(types->array[i], fd, |
1330 | 0, "", ""))) return 1; |
1331 | } |
1332 | return 0; |
1333 | } |
1334 | |
1335 | int print_log_header_events(facility_t *fac, FILE *fd) |
1336 | { |
47299663 |
1337 | sequence_t *events = &fac->events; |
1338 | char basename[PATH_MAX]; |
1339 | unsigned int facname_len; |
1340 | |
1341 | strncpy(basename, fac->name, PATH_MAX); |
1342 | facname_len = strlen(basename); |
1343 | strncat(basename, "_", PATH_MAX-facname_len); |
1344 | facname_len = strlen(basename); |
1345 | |
1346 | for(unsigned int i = 0; i < events->position; i++) { |
1347 | event_t *event = (event_t*)events->array[i]; |
1348 | strncpy(&basename[facname_len], event->name, PATH_MAX-facname_len); |
1349 | |
1350 | /* For each event, print structure, and then logging function */ |
1351 | fprintf(fd, "/* Event %s structures */\n", |
1352 | event->name); |
1353 | for(unsigned int j = 0; j < event->fields.position; j++) { |
1354 | /* For each unnamed type, print the definition */ |
1355 | field_t *f = (field_t*)event->fields.array[j]; |
1356 | type_descriptor_t *t = f->type; |
1357 | if(t->type_name == NULL) |
1358 | if((print_type_declaration(t, fd, 0, basename, f->name))) return 1; |
1359 | } |
1360 | fprintf(fd, "\n"); |
2d2d14a7 |
1361 | |
47299663 |
1362 | fprintf(fd, "/* Event %s logging function */\n", |
1363 | event->name); |
1364 | |
a3e6ce64 |
1365 | if(print_event_logging_function(basename, fac, event, fd)) return 1; |
47299663 |
1366 | |
1367 | fprintf(fd, "\n"); |
1368 | } |
1369 | |
2d2d14a7 |
1370 | return 0; |
1371 | } |
1372 | |
1373 | |
1374 | void print_log_header_tail(facility_t *fac, FILE *fd) |
1375 | { |
47299663 |
1376 | fprintf(fd, "#endif //CONFIG_LTT_FACILITY_%s\n\n", fac->capname); |
2d2d14a7 |
1377 | fprintf(fd, "#endif //_LTT_FACILITY_%s_H_\n",fac->capname); |
1378 | } |
1379 | |
1380 | int print_log_header(facility_t *fac) |
1381 | { |
1382 | char filename[PATH_MAX]; |
1383 | unsigned int filename_size = 0; |
1384 | FILE *fd; |
1385 | dprintf("%s\n", fac->name); |
1386 | |
1387 | strcpy(filename, "ltt-facility-"); |
1388 | filename_size = strlen(filename); |
1389 | |
1390 | strncat(filename, fac->name, PATH_MAX - filename_size); |
1391 | filename_size = strlen(filename); |
1392 | |
1393 | strncat(filename, ".h", PATH_MAX - filename_size); |
1394 | filename_size = strlen(filename); |
1395 | |
1396 | |
1397 | fd = fopen(filename, "w"); |
1398 | if(fd == NULL) { |
1399 | printf("Error opening file %s for writing : %s\n", |
1400 | filename, strerror(errno)); |
1401 | return errno; |
1402 | } |
1403 | |
1404 | /* Print file head */ |
1405 | print_log_header_head(fac, fd); |
1406 | |
1407 | /* print named types in declaration order */ |
1408 | if(print_log_header_types(fac, fd)) return 1; |
1409 | |
1410 | /* Print events */ |
1411 | if(print_log_header_events(fac, fd)) return 1; |
1412 | |
1413 | /* Print file tail */ |
1414 | print_log_header_tail(fac, fd); |
1415 | |
1416 | |
1417 | fclose(fd); |
1418 | |
1419 | return 0; |
1420 | } |
1421 | |
1422 | |
1423 | /* ltt-facility-id-name.h : facility id. |
1424 | * log_id_header */ |
1425 | int print_id_header(facility_t *fac) |
1426 | { |
1427 | char filename[PATH_MAX]; |
1428 | unsigned int filename_size = 0; |
1429 | FILE *fd; |
1430 | dprintf("%s\n", fac->name); |
1431 | |
1432 | strcpy(filename, "ltt-facility-id-"); |
1433 | filename_size = strlen(filename); |
1434 | |
1435 | strncat(filename, fac->name, PATH_MAX - filename_size); |
1436 | filename_size = strlen(filename); |
1437 | |
1438 | strncat(filename, ".h", PATH_MAX - filename_size); |
1439 | filename_size = strlen(filename); |
1440 | |
1441 | |
1442 | fd = fopen(filename, "w"); |
1443 | if(fd == NULL) { |
1444 | printf("Error opening file %s for writing : %s\n", |
1445 | filename, strerror(errno)); |
1446 | return errno; |
1447 | } |
1448 | |
1449 | fclose(fd); |
1450 | |
1451 | return 0; |
1452 | } |
1453 | |
1454 | |
1455 | /* ltt-facility-loader-name.h : facility specific loader info. |
1456 | * loader_header */ |
1457 | int print_loader_header(facility_t *fac) |
1458 | { |
1459 | char filename[PATH_MAX]; |
1460 | unsigned int filename_size = 0; |
1461 | FILE *fd; |
1462 | dprintf("%s\n", fac->name); |
1463 | |
1464 | strcpy(filename, "ltt-facility-loader-"); |
1465 | filename_size = strlen(filename); |
1466 | |
1467 | strncat(filename, fac->name, PATH_MAX - filename_size); |
1468 | filename_size = strlen(filename); |
1469 | |
1470 | strncat(filename, ".h", PATH_MAX - filename_size); |
1471 | filename_size = strlen(filename); |
1472 | |
1473 | |
1474 | fd = fopen(filename, "w"); |
1475 | if(fd == NULL) { |
1476 | printf("Error opening file %s for writing : %s\n", |
1477 | filename, strerror(errno)); |
1478 | return errno; |
1479 | } |
1480 | |
1481 | fclose(fd); |
1482 | |
1483 | return 0; |
1484 | } |
1485 | |
1486 | /* ltt-facility-loader-name.c : generic faciilty loader |
1487 | * loader_c */ |
1488 | int print_loader_c(facility_t *fac) |
1489 | { |
1490 | char filename[PATH_MAX]; |
1491 | unsigned int filename_size = 0; |
1492 | FILE *fd; |
1493 | dprintf("%s\n", fac->name); |
1494 | |
1495 | strcpy(filename, "ltt-facility-loader-"); |
1496 | filename_size = strlen(filename); |
1497 | |
1498 | strncat(filename, fac->name, PATH_MAX - filename_size); |
1499 | filename_size = strlen(filename); |
1500 | |
1501 | strncat(filename, ".c", PATH_MAX - filename_size); |
1502 | filename_size = strlen(filename); |
1503 | |
1504 | |
1505 | fd = fopen(filename, "w"); |
1506 | if(fd == NULL) { |
1507 | printf("Error opening file %s for writing : %s\n", |
1508 | filename, strerror(errno)); |
1509 | return errno; |
1510 | } |
1511 | |
1512 | |
1513 | fclose(fd); |
1514 | |
1515 | return 0; |
1516 | } |
1517 | |
1518 | |
1519 | |
92d82357 |
1520 | /* open facility */ |
1521 | /* code taken from ltt_facility_open in ltt/facility.c in lttv */ |
1522 | |
1523 | /***************************************************************************** |
1524 | *Function name |
1525 | * ltt_facility_open : open facilities |
1526 | *Input params |
1527 | * pathname : the path name of the facility |
1528 | * |
1529 | * Open the facility corresponding to the right checksum. |
1530 | * |
1531 | *returns the facility on success, NULL on error. |
1532 | ****************************************************************************/ |
1533 | facility_t *ltt_facility_open(char * pathname) |
1534 | { |
1535 | int ret = 0; |
1536 | char *token; |
1537 | parse_file_t in; |
1538 | facility_t * fac = NULL; |
1539 | unsigned long checksum; |
1540 | char buffer[BUFFER_SIZE]; |
1541 | int generated = FALSE; |
1542 | |
1543 | in.buffer = &(buffer[0]); |
1544 | in.lineno = 0; |
1545 | in.error = error_callback; |
1546 | in.name = pathname; |
1547 | in.unget = 0; |
1548 | |
1549 | in.fp = fopen(in.name, "r"); |
1550 | if(in.fp == NULL) { |
1551 | ret = 1; |
1552 | goto open_error; |
1553 | } |
1554 | |
1555 | while(1){ |
1556 | token = getToken(&in); |
1557 | if(in.type == ENDFILE) break; |
1558 | |
1559 | if(generated) { |
1560 | printf("More than one facility in the file. Only using the first one.\n"); |
1561 | break; |
1562 | } |
1563 | |
1564 | if(strcmp(token, "<")) in.error(&in,"not a facility file"); |
1565 | token = getName(&in); |
1566 | |
1567 | if(strcmp("facility",token) == 0) { |
1568 | fac = malloc(sizeof(facility_t)); |
1569 | fac->name = NULL; |
1570 | fac->description = NULL; |
1571 | sequence_init(&(fac->events)); |
1572 | table_init(&(fac->named_types)); |
1573 | sequence_init(&(fac->unnamed_types)); |
1574 | |
1575 | parseFacility(&in, fac); |
1576 | |
1577 | //check if any namedType is not defined |
1578 | checkNamedTypesImplemented(&fac->named_types); |
1579 | |
1580 | generateChecksum(fac->name, &checksum, &fac->events); |
a67cd958 |
1581 | |
92d82357 |
1582 | generated = TRUE; |
1583 | } |
1584 | else { |
1585 | printf("facility token was expected in file %s\n", in.name); |
1586 | ret = 1; |
1587 | goto parse_error; |
1588 | } |
1589 | } |
1590 | |
1591 | parse_error: |
1592 | fclose(in.fp); |
1593 | open_error: |
1594 | |
1595 | if(!generated) { |
1596 | printf("Cannot find facility %s\n", pathname); |
1597 | fac = NULL; |
1598 | } |
1599 | |
1600 | return fac; |
1601 | } |
1602 | |
1603 | /* Close the facility */ |
1604 | void ltt_facility_close(facility_t *fac) |
1605 | { |
1606 | free(fac->name); |
1607 | free(fac->capname); |
1608 | free(fac->description); |
1609 | freeEvents(&fac->events); |
1610 | sequence_dispose(&fac->events); |
1611 | freeNamedType(&fac->named_types); |
1612 | table_dispose(&fac->named_types); |
1613 | freeTypes(&fac->unnamed_types); |
1614 | sequence_dispose(&fac->unnamed_types); |
1615 | free(fac); |
1616 | } |
1617 | |
1618 | |
1619 | /* Show help */ |
1620 | void show_help(int argc, char ** argv) |
1621 | { |
1622 | printf("Genevent help : \n"); |
1623 | printf("\n"); |
1624 | printf("Use %s name.xml\n", argv[0]); |
1625 | printf("to create :\n"); |
1626 | printf("ltt-facility-name.h\n"); |
1627 | printf("ltt-facility-id-name.h\n"); |
1628 | printf("ltt-facility-loader-name.h\n"); |
1629 | printf("ltt-facility-loader-name.c\n"); |
1630 | printf("In the current directory.\n"); |
1631 | printf("\n"); |
1632 | } |
1633 | |
1634 | /* Parse program arguments */ |
1635 | /* Return values : |
1636 | * 0 : continue program |
1637 | * -1 : stop program, return 0 |
1638 | * > 0 : stop program, return value as exit. |
1639 | */ |
1640 | int check_args(int argc, char **argv) |
1641 | { |
1642 | if(argc < 2) { |
1643 | printf("Not enough arguments\n"); |
1644 | show_help(argc, argv); |
1645 | return EINVAL; |
1646 | } |
1647 | |
1648 | if(strcmp(argv[1], "-h") == 0) { |
1649 | show_help(argc, argv); |
1650 | return -1; |
1651 | } |
1652 | |
1653 | return 0; |
1654 | } |
1655 | |
1656 | int main(int argc, char **argv) |
1657 | { |
1658 | int err = 0; |
1659 | facility_t *fac; |
1660 | |
1661 | err = check_args(argc, argv); |
1662 | if(err > 0) return err; |
1663 | else if(err < 0) return 0; |
1664 | |
1665 | /* open the facility */ |
1666 | fac = ltt_facility_open(argv[1]); |
1667 | if(fac == NULL) { |
1668 | printf("Error opening file %s for reading : %s\n", |
1669 | argv[1], strerror(errno)); |
1670 | return errno; |
1671 | } |
1672 | |
1673 | /* generate the output C files */ |
1674 | |
1675 | |
2d2d14a7 |
1676 | /* ltt-facility-name.h : main logging header. |
1677 | * log_header */ |
1678 | err = print_log_header(fac); |
1679 | if(err) return err; |
92d82357 |
1680 | |
2d2d14a7 |
1681 | /* ltt-facility-id-name.h : facility id. |
1682 | * log_id_header */ |
1683 | err = print_id_header(fac); |
1684 | if(err) return err; |
92d82357 |
1685 | |
2d2d14a7 |
1686 | /* ltt-facility-loader-name.h : facility specific loader info. |
1687 | * loader_header */ |
1688 | err = print_loader_header(fac); |
1689 | if(err) return err; |
1690 | |
1691 | /* ltt-facility-loader-name.c : generic faciilty loader |
1692 | * loader_c */ |
1693 | err = print_loader_c(fac); |
1694 | if(err) return err; |
92d82357 |
1695 | |
1696 | /* close the facility */ |
1697 | ltt_facility_close(fac); |
1698 | |
1699 | return 0; |
1700 | } |
1701 | |
1702 | |