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 | |
2d2d14a7 |
328 | /* print type declaration. |
329 | * |
330 | * Copied from construct_types_and_fields in LTTV facility.c */ |
331 | |
332 | int 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 | ****************************************************************************/ |
477 | void 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 | ¤t_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 | ****************************************************************************/ |
500 | void 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 | ¤t_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 | ****************************************************************************/ |
537 | void 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 | ¤t_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 | ¤t_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 | |
690 | size_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 */ |
811 | int 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 */ |
923 | int 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 | |
994 | void 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 |
1005 | int 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 | |
1019 | int 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 | |
1058 | void 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 | |
1064 | int 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 */ |
1109 | int 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 */ |
1141 | int 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 */ |
1172 | int 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 | ****************************************************************************/ |
1217 | facility_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); |
1277 | open_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 */ |
1288 | void 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 */ |
1304 | void 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 | */ |
1324 | int 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 | |
1340 | int 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 | |