array fixes
[lttv.git] / genevent-new / genevent.c
CommitLineData
92d82357 1/******************************************************************************
2 * Genevent
3 *
4 * Event generator. XML to logging C code converter.
5 *
6 * Program parameters :
7 * ./genevent name.xml
8 *
9 * Will generate ltt-facility-name.h, ltt-facility-id-name.h
10 * ltt-facility-loader-name.c, ltt-facility-loader-name.h
11 * in the current directory.
12 *
13 * Supports :
14 * - C Alignment
15 * - C types : struct, union, enum, basic types.
16 * - Architectures : LP32, ILP32, ILP64, LLP64, LP64.
17 *
18 * Additionnal structures supported :
19 * - embedded variable size strings
20 * - embedded variable size arrays
21 * - embedded variable size sequences
22 *
23 * Notes :
24 * (1)
25 * enums are limited to integer type, as this is what is used in C. Note,
26 * however, that ISO/IEC 9899:TC2 specify that the type of enum can be char,
27 * unsigned int or int. This is implementation defined (compiler). That's why we
28 * add a check for sizeof enum.
29 *
30 * (2)
31 * Because of archtecture defined type sizes, we need to ask for ltt_align
32 * (which gives the alignment) by passing basic types, not their actual sizes.
33 * It's up to ltt_align to determine sizes of types.
34 *
35 * Note that, from
36 * http://www.usenix.org/publications/login/standards/10.data.html
37 * (Andrew Josey <a.josey@opengroup.org>) :
38 *
39 * Data Type LP32 ILP32 ILP64 LLP64 LP64
40 * char 8 8 8 8 8
41 * short 16 16 16 16 16
42 * int32 32
43 * int 16 32 64 32 32
44 * long 32 32 64 32 64
45 * long long (int64) 64
46 * pointer 32 32 64 64 64
47 *
48 * With these constraints :
49 * sizeof(char) <= sizeof(short) <= sizeof(int)
50 * <= sizeof(long) = sizeof(size_t)
51 *
52 * and therefore sizeof(long) <= sizeof(pointer) <= sizeof(size_t)
53 *
54 * Which means we only have to remember which is the biggest type in a structure
55 * to know the structure's alignment.
56 */
57
2d2d14a7 58#define _GNU_SOURCE
59#include <limits.h>
60#include <stdlib.h>
92d82357 61#include <errno.h>
62#include <sys/types.h>
63#include <sys/stat.h>
64#include <fcntl.h>
65#include <stdio.h>
66#include <string.h>
67#include <unistd.h>
2d2d14a7 68#include <assert.h>
92d82357 69
70#include "genevent.h"
71#include "parser.h"
72
73
74#define TRUE 1
75#define FALSE (!TRUE)
76
2d2d14a7 77/* Debugging printf */
78#ifdef DEBUG
79#define dprintf(...) \
80 do {\
81 printf(__FILE__ ",%u,%s: ",\
82 __LINE__, __func__);\
83 printf(__VA_ARGS__);\
84 } while(0)
85#else
86#define dprintf(...)
87#endif
88
89
92d82357 90/* Code printing */
91
2d2d14a7 92void print_tabs(unsigned int tabs, FILE *fd)
93{
94 for(unsigned int i = 0; i<tabs;i++)
95 fprintf(fd, "\t");
96}
97
92d82357 98/* Type size checking */
2d2d14a7 99/* Uses #error in the generated code to signal error and stop the compiler */
92d82357 100int print_check(int fd);
101
102
103/* Print types */
104int print_types(int fd);
105
106
107/* Print events */
108int print_events(int fd);
109
110
2d2d14a7 111/* print type.
112 *
113 * Copied from construct_types_and_fields in LTTV facility.c */
114
115int print_type(type_descriptor_t * td, FILE *fd, unsigned int tabs,
116 char *nest_name, char *field_name)
117{
118 char basename[PATH_MAX];
119 unsigned int basename_len = 0;
120
121 strcpy(basename, nest_name);
122 basename_len = strlen(basename);
123
124 /* For a named type, we use the type_name directly */
125 if(td->type_name != NULL) {
126 strncpy(basename, td->type_name, PATH_MAX);
127 basename_len = strlen(basename);
128 } else {
129 /* For a unnamed type, there must be a field name */
7b175edc 130 if((basename_len != 0)
131 && (basename[basename_len-1] != '_')
132 && (field_name[0] != '\0')) {
2d2d14a7 133 strncat(basename, "_", PATH_MAX - basename_len);
134 basename_len = strlen(basename);
135 }
136 strncat(basename, field_name, PATH_MAX - basename_len);
137 }
138
139 switch(td->type) {
140 case INT_FIXED:
141 fprintf(fd, "%s", intOutputTypes[getSizeindex(td->size)]);
142 break;
143 case UINT_FIXED:
144 fprintf(fd, "%s", uintOutputTypes[getSizeindex(td->size)]);
145 break;
146 case CHAR:
147 fprintf(fd, "signed char");
148 break;
149 case UCHAR:
150 fprintf(fd, "unsigned char");
151 break;
152 case SHORT:
153 fprintf(fd, "short");
154 break;
155 case USHORT:
156 fprintf(fd, "unsigned short");
157 break;
158 case INT:
159 fprintf(fd, "int");
160 break;
161 case UINT:
162 fprintf(fd, "unsigned int");
163 break;
164 case FLOAT:
165 fprintf(fd, "%s", floatOutputTypes[getSizeindex(td->size)]);
166 break;
167 case POINTER:
168 fprintf(fd, "void *");
169 break;
170 case LONG:
171 fprintf(fd, "long");
172 break;
173 case ULONG:
174 fprintf(fd, "unsigned long");
175 break;
176 case SIZE_T:
177 fprintf(fd, "size_t");
178 break;
179 case SSIZE_T:
180 fprintf(fd, "ssize_t");
181 break;
182 case OFF_T:
183 fprintf(fd, "off_t");
184 break;
185 case STRING:
186 fprintf(fd, "char *");
187 break;
188 case ENUM:
189 fprintf(fd, "enum lttng_%s", basename);
190 break;
191 case ARRAY:
192 fprintf(fd, "lttng_array_%s", basename);
193 break;
194 case SEQUENCE:
195 fprintf(fd, "lttng_sequence_%s", basename);
196 break;
197 case STRUCT:
198 fprintf(fd, "struct lttng_%s", basename);
199 break;
200 case UNION:
201 fprintf(fd, "union lttng_%s", basename);
202 break;
203 default:
204 printf("print_type : unknown type\n");
205 return 1;
206 }
207
208 return 0;
209}
210
211/* print type declaration.
212 *
213 * Copied from construct_types_and_fields in LTTV facility.c */
214
215int print_type_declaration(type_descriptor_t * td, FILE *fd, unsigned int tabs,
216 char *nest_name, char *field_name)
217{
218 char basename[PATH_MAX];
219 unsigned int basename_len = 0;
220
7b175edc 221 strncpy(basename, nest_name, PATH_MAX);
2d2d14a7 222 basename_len = strlen(basename);
223
224 /* For a named type, we use the type_name directly */
225 if(td->type_name != NULL) {
226 strncpy(basename, td->type_name, PATH_MAX);
227 basename_len = strlen(basename);
228 } else {
7b175edc 229 /* For a unnamed type, there must be a field name, except for
230 * the array. */
231 if((basename_len != 0)
232 && (basename[basename_len-1] != '_'
233 && (field_name[0] != '\0'))) {
2d2d14a7 234 strncat(basename, "_", PATH_MAX - basename_len);
235 basename_len = strlen(basename);
236 }
237 strncat(basename, field_name, PATH_MAX - basename_len);
2d2d14a7 238 }
239
240 switch(td->type) {
241 case ENUM:
242 fprintf(fd, "enum lttng_%s", basename);
243 fprintf(fd, " {\n");
244 for(unsigned int i=0;i<td->labels.position;i++){
245 print_tabs(1, fd);
246 fprintf(fd, "LTTNG_%s", ((char*)(td->labels.array[i])));
247 fprintf(fd, ",\n");
248 }
249 fprintf(fd, "};\n");
250 fprintf(fd, "\n");
251 break;
252
253 case ARRAY:
7b175edc 254 dprintf("%s\n", basename);
2d2d14a7 255 assert(td->size >= 0);
256 if(td->nested_type->type_name == NULL) {
257 /* Not a named nested type : we must print its declaration first */
258 if(print_type_declaration(td->nested_type,
259 fd, 0, basename, "")) return 1;
260 }
261 fprintf(fd, "#define LTTNG_ARRAY_SIZE_%s %llu\n", basename,
262 td->size);
47299663 263 if(print_type(td->nested_type, fd, tabs, basename, "")) return 1;
2d2d14a7 264 fprintf(fd, " lttng_array_%s[LTTNG_ARRAY_SIZE_%s];\n", basename,
265 basename);
266 fprintf(fd, "\n");
267 break;
268 case SEQUENCE:
269 if(td->nested_type->type_name == NULL) {
270 /* Not a named nested type : we must print its declaration first */
271 if(print_type_declaration(td->nested_type,
272 fd, 0, basename, "")) return 1;
273 }
274 fprintf(fd, "typedef struct lttng_sequence_%s lttng_sequence_%s;\n",
275 basename,
276 basename);
277 fprintf(fd, "struct lttng_sequence_%s", basename);
278 fprintf(fd, " {\n");
279 print_tabs(1, fd);
280 fprintf(fd, "unsigned int len;\n");
281 print_tabs(1, fd);
47299663 282 if(print_type(td->nested_type, fd, tabs, basename, "")) return 1;
2d2d14a7 283 fprintf(fd, " *array;\n");
284 fprintf(fd, "};\n");
285 fprintf(fd, "\n");
286 break;
287
288 case STRUCT:
289 for(unsigned int i=0;i<td->fields.position;i++){
290 field_t *field = (field_t*)(td->fields.array[i]);
291 type_descriptor_t *type = field->type;
292 if(type->type_name == NULL) {
293 /* Not a named nested type : we must print its declaration first */
294 if(print_type_declaration(type,
295 fd, 0, basename, field->name)) return 1;
296 }
297 }
298 fprintf(fd, "struct lttng_%s", basename);
299 fprintf(fd, " {\n");
300 for(unsigned int i=0;i<td->fields.position;i++){
301 field_t *field = (field_t*)(td->fields.array[i]);
302 type_descriptor_t *type = field->type;
303 print_tabs(1, fd);
47299663 304 if(print_type(type, fd, tabs, basename, field->name)) return 1;
2d2d14a7 305 fprintf(fd, " ");
306 fprintf(fd, "%s", field->name);
307 fprintf(fd, ";\n");
308 }
309 fprintf(fd, "};\n");
310 fprintf(fd, "\n");
311 break;
312 case UNION:
313 /* TODO : Do not allow variable length fields in a union */
314 for(unsigned int i=0;i<td->fields.position;i++){
315 field_t *field = (field_t*)(td->fields.array[i]);
316 type_descriptor_t *type = field->type;
317 if(type->type_name == NULL) {
318 /* Not a named nested type : we must print its declaration first */
47299663 319 if(print_type_declaration(type,
320 fd, 0, basename, field->name)) return 1;
2d2d14a7 321 }
322 }
323 fprintf(fd, "union lttng_%s", basename);
324 fprintf(fd, " {\n");
325 for(unsigned i=0;i<td->fields.position;i++){
326 field_t *field = (field_t*)(td->fields.array[i]);
327 type_descriptor_t *type = field->type;
328 print_tabs(1, fd);
47299663 329 if(print_type(type, fd, tabs, basename, field->name)) return 1;
2d2d14a7 330 fprintf(fd, " ");
331 fprintf(fd, "%s", field->name);
332 fprintf(fd, ";\n");
333 }
334 fprintf(fd, "};\n");
335 fprintf(fd, "\n");
336 break;
337 default:
338 dprintf("print_type_declaration : unknown type or nothing to declare.\n");
339 break;
340 }
341
342 return 0;
343}
344
47299663 345/* Print the logging function of an event. This is the core of genevent */
346int print_event_logging_function(char *basename, event_t *event, FILE *fd)
347{
348 fprintf(fd, "static inline void trace_%s(\n", basename);
349 for(unsigned int j = 0; j < event->fields.position; j++) {
350 /* For each field, print the function argument */
351 field_t *f = (field_t*)event->fields.array[j];
352 type_descriptor_t *t = f->type;
353 print_tabs(2, fd);
354 if(print_type(t, fd, 0, basename, f->name)) return 1;
355 fprintf(fd, " %s", f->name);
356 if(j < event->fields.position-1) {
357 fprintf(fd, ",");
358 fprintf(fd, "\n");
359 }
360 }
361 if(event->fields.position == 0) {
362 print_tabs(2, fd);
363 fprintf(fd, "void");
364 }
365 fprintf(fd,")\n");
366 fprintf(fd, "#ifndef CONFIG_LTT\n");
367 fprintf(fd, "{\n");
368 fprintf(fd, "}\n");
369 fprintf(fd,"#else\n");
370 fprintf(fd, "{\n");
371
2d2d14a7 372
47299663 373 fprintf(fd, "}\n");
374 fprintf(fd, "#endif //CONFIG_LTT\n\n");
375 return 0;
376}
2d2d14a7 377
378
379/* ltt-facility-name.h : main logging header.
380 * log_header */
381
382void print_log_header_head(facility_t *fac, FILE *fd)
383{
384 fprintf(fd, "#ifndef _LTT_FACILITY_%s_H_\n", fac->capname);
385 fprintf(fd, "#define _LTT_FACILITY_%s_H_\n\n", fac->capname);
47299663 386 fprintf(fd, "\n");
387 fprintf(fd, "/* Facility activation at compile time. */\n");
388 fprintf(fd, "#ifdef CONFIG_LTT_FACILITY_%s\n\n", fac->capname);
2d2d14a7 389}
390
391
392
2d2d14a7 393int print_log_header_types(facility_t *fac, FILE *fd)
394{
395 sequence_t *types = &fac->named_types.values;
396 fprintf(fd, "/* Named types */\n");
397 fprintf(fd, "\n");
398
399 for(unsigned int i = 0; i < types->position; i++) {
400 /* For each named type, print the definition */
401 if((print_type_declaration(types->array[i], fd,
402 0, "", ""))) return 1;
403 }
404 return 0;
405}
406
407int print_log_header_events(facility_t *fac, FILE *fd)
408{
47299663 409 sequence_t *events = &fac->events;
410 char basename[PATH_MAX];
411 unsigned int facname_len;
412
413 strncpy(basename, fac->name, PATH_MAX);
414 facname_len = strlen(basename);
415 strncat(basename, "_", PATH_MAX-facname_len);
416 facname_len = strlen(basename);
417
418 for(unsigned int i = 0; i < events->position; i++) {
419 event_t *event = (event_t*)events->array[i];
420 strncpy(&basename[facname_len], event->name, PATH_MAX-facname_len);
421
422 /* For each event, print structure, and then logging function */
423 fprintf(fd, "/* Event %s structures */\n",
424 event->name);
425 for(unsigned int j = 0; j < event->fields.position; j++) {
426 /* For each unnamed type, print the definition */
427 field_t *f = (field_t*)event->fields.array[j];
428 type_descriptor_t *t = f->type;
429 if(t->type_name == NULL)
430 if((print_type_declaration(t, fd, 0, basename, f->name))) return 1;
431 }
432 fprintf(fd, "\n");
2d2d14a7 433
47299663 434 fprintf(fd, "/* Event %s logging function */\n",
435 event->name);
436
437 if(print_event_logging_function(basename, event, fd)) return 1;
438
439 fprintf(fd, "\n");
440 }
441
2d2d14a7 442 return 0;
443}
444
445
446void print_log_header_tail(facility_t *fac, FILE *fd)
447{
47299663 448 fprintf(fd, "#endif //CONFIG_LTT_FACILITY_%s\n\n", fac->capname);
2d2d14a7 449 fprintf(fd, "#endif //_LTT_FACILITY_%s_H_\n",fac->capname);
450}
451
452int print_log_header(facility_t *fac)
453{
454 char filename[PATH_MAX];
455 unsigned int filename_size = 0;
456 FILE *fd;
457 dprintf("%s\n", fac->name);
458
459 strcpy(filename, "ltt-facility-");
460 filename_size = strlen(filename);
461
462 strncat(filename, fac->name, PATH_MAX - filename_size);
463 filename_size = strlen(filename);
464
465 strncat(filename, ".h", PATH_MAX - filename_size);
466 filename_size = strlen(filename);
467
468
469 fd = fopen(filename, "w");
470 if(fd == NULL) {
471 printf("Error opening file %s for writing : %s\n",
472 filename, strerror(errno));
473 return errno;
474 }
475
476 /* Print file head */
477 print_log_header_head(fac, fd);
478
479 /* print named types in declaration order */
480 if(print_log_header_types(fac, fd)) return 1;
481
482 /* Print events */
483 if(print_log_header_events(fac, fd)) return 1;
484
485 /* Print file tail */
486 print_log_header_tail(fac, fd);
487
488
489 fclose(fd);
490
491 return 0;
492}
493
494
495/* ltt-facility-id-name.h : facility id.
496 * log_id_header */
497int print_id_header(facility_t *fac)
498{
499 char filename[PATH_MAX];
500 unsigned int filename_size = 0;
501 FILE *fd;
502 dprintf("%s\n", fac->name);
503
504 strcpy(filename, "ltt-facility-id-");
505 filename_size = strlen(filename);
506
507 strncat(filename, fac->name, PATH_MAX - filename_size);
508 filename_size = strlen(filename);
509
510 strncat(filename, ".h", PATH_MAX - filename_size);
511 filename_size = strlen(filename);
512
513
514 fd = fopen(filename, "w");
515 if(fd == NULL) {
516 printf("Error opening file %s for writing : %s\n",
517 filename, strerror(errno));
518 return errno;
519 }
520
521 fclose(fd);
522
523 return 0;
524}
525
526
527/* ltt-facility-loader-name.h : facility specific loader info.
528 * loader_header */
529int print_loader_header(facility_t *fac)
530{
531 char filename[PATH_MAX];
532 unsigned int filename_size = 0;
533 FILE *fd;
534 dprintf("%s\n", fac->name);
535
536 strcpy(filename, "ltt-facility-loader-");
537 filename_size = strlen(filename);
538
539 strncat(filename, fac->name, PATH_MAX - filename_size);
540 filename_size = strlen(filename);
541
542 strncat(filename, ".h", PATH_MAX - filename_size);
543 filename_size = strlen(filename);
544
545
546 fd = fopen(filename, "w");
547 if(fd == NULL) {
548 printf("Error opening file %s for writing : %s\n",
549 filename, strerror(errno));
550 return errno;
551 }
552
553 fclose(fd);
554
555 return 0;
556}
557
558/* ltt-facility-loader-name.c : generic faciilty loader
559 * loader_c */
560int print_loader_c(facility_t *fac)
561{
562 char filename[PATH_MAX];
563 unsigned int filename_size = 0;
564 FILE *fd;
565 dprintf("%s\n", fac->name);
566
567 strcpy(filename, "ltt-facility-loader-");
568 filename_size = strlen(filename);
569
570 strncat(filename, fac->name, PATH_MAX - filename_size);
571 filename_size = strlen(filename);
572
573 strncat(filename, ".c", PATH_MAX - filename_size);
574 filename_size = strlen(filename);
575
576
577 fd = fopen(filename, "w");
578 if(fd == NULL) {
579 printf("Error opening file %s for writing : %s\n",
580 filename, strerror(errno));
581 return errno;
582 }
583
584
585 fclose(fd);
586
587 return 0;
588}
589
590
591
92d82357 592/* open facility */
593/* code taken from ltt_facility_open in ltt/facility.c in lttv */
594
595/*****************************************************************************
596 *Function name
597 * ltt_facility_open : open facilities
598 *Input params
599 * pathname : the path name of the facility
600 *
601 * Open the facility corresponding to the right checksum.
602 *
603 *returns the facility on success, NULL on error.
604 ****************************************************************************/
605facility_t *ltt_facility_open(char * pathname)
606{
607 int ret = 0;
608 char *token;
609 parse_file_t in;
610 facility_t * fac = NULL;
611 unsigned long checksum;
612 char buffer[BUFFER_SIZE];
613 int generated = FALSE;
614
615 in.buffer = &(buffer[0]);
616 in.lineno = 0;
617 in.error = error_callback;
618 in.name = pathname;
619 in.unget = 0;
620
621 in.fp = fopen(in.name, "r");
622 if(in.fp == NULL) {
623 ret = 1;
624 goto open_error;
625 }
626
627 while(1){
628 token = getToken(&in);
629 if(in.type == ENDFILE) break;
630
631 if(generated) {
632 printf("More than one facility in the file. Only using the first one.\n");
633 break;
634 }
635
636 if(strcmp(token, "<")) in.error(&in,"not a facility file");
637 token = getName(&in);
638
639 if(strcmp("facility",token) == 0) {
640 fac = malloc(sizeof(facility_t));
641 fac->name = NULL;
642 fac->description = NULL;
643 sequence_init(&(fac->events));
644 table_init(&(fac->named_types));
645 sequence_init(&(fac->unnamed_types));
646
647 parseFacility(&in, fac);
648
649 //check if any namedType is not defined
650 checkNamedTypesImplemented(&fac->named_types);
651
652 generateChecksum(fac->name, &checksum, &fac->events);
653
654 generated = TRUE;
655 }
656 else {
657 printf("facility token was expected in file %s\n", in.name);
658 ret = 1;
659 goto parse_error;
660 }
661 }
662
663 parse_error:
664 fclose(in.fp);
665open_error:
666
667 if(!generated) {
668 printf("Cannot find facility %s\n", pathname);
669 fac = NULL;
670 }
671
672 return fac;
673}
674
675/* Close the facility */
676void ltt_facility_close(facility_t *fac)
677{
678 free(fac->name);
679 free(fac->capname);
680 free(fac->description);
681 freeEvents(&fac->events);
682 sequence_dispose(&fac->events);
683 freeNamedType(&fac->named_types);
684 table_dispose(&fac->named_types);
685 freeTypes(&fac->unnamed_types);
686 sequence_dispose(&fac->unnamed_types);
687 free(fac);
688}
689
690
691/* Show help */
692void show_help(int argc, char ** argv)
693{
694 printf("Genevent help : \n");
695 printf("\n");
696 printf("Use %s name.xml\n", argv[0]);
697 printf("to create :\n");
698 printf("ltt-facility-name.h\n");
699 printf("ltt-facility-id-name.h\n");
700 printf("ltt-facility-loader-name.h\n");
701 printf("ltt-facility-loader-name.c\n");
702 printf("In the current directory.\n");
703 printf("\n");
704}
705
706/* Parse program arguments */
707/* Return values :
708 * 0 : continue program
709 * -1 : stop program, return 0
710 * > 0 : stop program, return value as exit.
711 */
712int check_args(int argc, char **argv)
713{
714 if(argc < 2) {
715 printf("Not enough arguments\n");
716 show_help(argc, argv);
717 return EINVAL;
718 }
719
720 if(strcmp(argv[1], "-h") == 0) {
721 show_help(argc, argv);
722 return -1;
723 }
724
725 return 0;
726}
727
728int main(int argc, char **argv)
729{
730 int err = 0;
731 facility_t *fac;
732
733 err = check_args(argc, argv);
734 if(err > 0) return err;
735 else if(err < 0) return 0;
736
737 /* open the facility */
738 fac = ltt_facility_open(argv[1]);
739 if(fac == NULL) {
740 printf("Error opening file %s for reading : %s\n",
741 argv[1], strerror(errno));
742 return errno;
743 }
744
745 /* generate the output C files */
746
747
2d2d14a7 748 /* ltt-facility-name.h : main logging header.
749 * log_header */
750 err = print_log_header(fac);
751 if(err) return err;
92d82357 752
2d2d14a7 753 /* ltt-facility-id-name.h : facility id.
754 * log_id_header */
755 err = print_id_header(fac);
756 if(err) return err;
92d82357 757
2d2d14a7 758 /* ltt-facility-loader-name.h : facility specific loader info.
759 * loader_header */
760 err = print_loader_header(fac);
761 if(err) return err;
762
763 /* ltt-facility-loader-name.c : generic faciilty loader
764 * loader_c */
765 err = print_loader_c(fac);
766 if(err) return err;
92d82357 767
768 /* close the facility */
769 ltt_facility_close(fac);
770
771 return 0;
772}
773
774
This page took 0.060069 seconds and 4 git commands to generate.