test xml
[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 */
130 if(basename_len != 0) {
131 strncat(basename, "_", PATH_MAX - basename_len);
132 basename_len = strlen(basename);
133 }
134 strncat(basename, field_name, PATH_MAX - basename_len);
135 }
136
137 switch(td->type) {
138 case INT_FIXED:
139 fprintf(fd, "%s", intOutputTypes[getSizeindex(td->size)]);
140 break;
141 case UINT_FIXED:
142 fprintf(fd, "%s", uintOutputTypes[getSizeindex(td->size)]);
143 break;
144 case CHAR:
145 fprintf(fd, "signed char");
146 break;
147 case UCHAR:
148 fprintf(fd, "unsigned char");
149 break;
150 case SHORT:
151 fprintf(fd, "short");
152 break;
153 case USHORT:
154 fprintf(fd, "unsigned short");
155 break;
156 case INT:
157 fprintf(fd, "int");
158 break;
159 case UINT:
160 fprintf(fd, "unsigned int");
161 break;
162 case FLOAT:
163 fprintf(fd, "%s", floatOutputTypes[getSizeindex(td->size)]);
164 break;
165 case POINTER:
166 fprintf(fd, "void *");
167 break;
168 case LONG:
169 fprintf(fd, "long");
170 break;
171 case ULONG:
172 fprintf(fd, "unsigned long");
173 break;
174 case SIZE_T:
175 fprintf(fd, "size_t");
176 break;
177 case SSIZE_T:
178 fprintf(fd, "ssize_t");
179 break;
180 case OFF_T:
181 fprintf(fd, "off_t");
182 break;
183 case STRING:
184 fprintf(fd, "char *");
185 break;
186 case ENUM:
187 fprintf(fd, "enum lttng_%s", basename);
188 break;
189 case ARRAY:
190 fprintf(fd, "lttng_array_%s", basename);
191 break;
192 case SEQUENCE:
193 fprintf(fd, "lttng_sequence_%s", basename);
194 break;
195 case STRUCT:
196 fprintf(fd, "struct lttng_%s", basename);
197 break;
198 case UNION:
199 fprintf(fd, "union lttng_%s", basename);
200 break;
201 default:
202 printf("print_type : unknown type\n");
203 return 1;
204 }
205
206 return 0;
207}
208
209/* print type declaration.
210 *
211 * Copied from construct_types_and_fields in LTTV facility.c */
212
213int print_type_declaration(type_descriptor_t * td, FILE *fd, unsigned int tabs,
214 char *nest_name, char *field_name)
215{
216 char basename[PATH_MAX];
217 unsigned int basename_len = 0;
218
219 strcpy(basename, nest_name);
220 basename_len = strlen(basename);
221
222 /* For a named type, we use the type_name directly */
223 if(td->type_name != NULL) {
224 strncpy(basename, td->type_name, PATH_MAX);
225 basename_len = strlen(basename);
226 } else {
227 /* For a unnamed type, there must be a field name */
228 if(basename_len != 0) {
229 strncat(basename, "_", PATH_MAX - basename_len);
230 basename_len = strlen(basename);
231 }
232 strncat(basename, field_name, PATH_MAX - basename_len);
233 dprintf("%s\n", field_name);
234 }
235
236 switch(td->type) {
237 case ENUM:
238 fprintf(fd, "enum lttng_%s", basename);
239 fprintf(fd, " {\n");
240 for(unsigned int i=0;i<td->labels.position;i++){
241 print_tabs(1, fd);
242 fprintf(fd, "LTTNG_%s", ((char*)(td->labels.array[i])));
243 fprintf(fd, ",\n");
244 }
245 fprintf(fd, "};\n");
246 fprintf(fd, "\n");
247 break;
248
249 case ARRAY:
250 assert(td->size >= 0);
251 if(td->nested_type->type_name == NULL) {
252 /* Not a named nested type : we must print its declaration first */
253 if(print_type_declaration(td->nested_type,
254 fd, 0, basename, "")) return 1;
255 }
256 fprintf(fd, "#define LTTNG_ARRAY_SIZE_%s %llu\n", basename,
257 td->size);
258 print_type(td->nested_type, fd, tabs, basename, "");
259 fprintf(fd, " lttng_array_%s[LTTNG_ARRAY_SIZE_%s];\n", basename,
260 basename);
261 fprintf(fd, "\n");
262 break;
263 case SEQUENCE:
264 if(td->nested_type->type_name == NULL) {
265 /* Not a named nested type : we must print its declaration first */
266 if(print_type_declaration(td->nested_type,
267 fd, 0, basename, "")) return 1;
268 }
269 fprintf(fd, "typedef struct lttng_sequence_%s lttng_sequence_%s;\n",
270 basename,
271 basename);
272 fprintf(fd, "struct lttng_sequence_%s", basename);
273 fprintf(fd, " {\n");
274 print_tabs(1, fd);
275 fprintf(fd, "unsigned int len;\n");
276 print_tabs(1, fd);
277 print_type(td->nested_type, fd, tabs, basename, "");
278 fprintf(fd, " *array;\n");
279 fprintf(fd, "};\n");
280 fprintf(fd, "\n");
281 break;
282
283 case STRUCT:
284 for(unsigned int i=0;i<td->fields.position;i++){
285 field_t *field = (field_t*)(td->fields.array[i]);
286 type_descriptor_t *type = field->type;
287 if(type->type_name == NULL) {
288 /* Not a named nested type : we must print its declaration first */
289 if(print_type_declaration(type,
290 fd, 0, basename, field->name)) return 1;
291 }
292 }
293 fprintf(fd, "struct lttng_%s", basename);
294 fprintf(fd, " {\n");
295 for(unsigned int i=0;i<td->fields.position;i++){
296 field_t *field = (field_t*)(td->fields.array[i]);
297 type_descriptor_t *type = field->type;
298 print_tabs(1, fd);
299 print_type(type, fd, tabs, basename, field->name);
300 fprintf(fd, " ");
301 fprintf(fd, "%s", field->name);
302 fprintf(fd, ";\n");
303 }
304 fprintf(fd, "};\n");
305 fprintf(fd, "\n");
306 break;
307 case UNION:
308 /* TODO : Do not allow variable length fields in a union */
309 for(unsigned int i=0;i<td->fields.position;i++){
310 field_t *field = (field_t*)(td->fields.array[i]);
311 type_descriptor_t *type = field->type;
312 if(type->type_name == NULL) {
313 /* Not a named nested type : we must print its declaration first */
314 //if(print_type_declaration(type,
315 // fd, 0, basename, field->name)) return 1;
316 }
317 }
318 fprintf(fd, "union lttng_%s", basename);
319 fprintf(fd, " {\n");
320 for(unsigned i=0;i<td->fields.position;i++){
321 field_t *field = (field_t*)(td->fields.array[i]);
322 type_descriptor_t *type = field->type;
323 print_tabs(1, fd);
324 print_type(type, fd, tabs, basename, field->name);
325 fprintf(fd, " ");
326 fprintf(fd, "%s", field->name);
327 fprintf(fd, ";\n");
328 }
329 fprintf(fd, "};\n");
330 fprintf(fd, "\n");
331 break;
332 default:
333 dprintf("print_type_declaration : unknown type or nothing to declare.\n");
334 break;
335 }
336
337 return 0;
338}
339
340
341
342
343/* ltt-facility-name.h : main logging header.
344 * log_header */
345
346void print_log_header_head(facility_t *fac, FILE *fd)
347{
348 fprintf(fd, "#ifndef _LTT_FACILITY_%s_H_\n", fac->capname);
349 fprintf(fd, "#define _LTT_FACILITY_%s_H_\n\n", fac->capname);
350}
351
352
353
354
355int print_log_header_types(facility_t *fac, FILE *fd)
356{
357 sequence_t *types = &fac->named_types.values;
358 fprintf(fd, "/* Named types */\n");
359 fprintf(fd, "\n");
360
361 for(unsigned int i = 0; i < types->position; i++) {
362 /* For each named type, print the definition */
363 if((print_type_declaration(types->array[i], fd,
364 0, "", ""))) return 1;
365 }
366 return 0;
367}
368
369int print_log_header_events(facility_t *fac, FILE *fd)
370{
371
372 return 0;
373}
374
375
376void print_log_header_tail(facility_t *fac, FILE *fd)
377{
378 fprintf(fd, "#endif //_LTT_FACILITY_%s_H_\n",fac->capname);
379}
380
381int print_log_header(facility_t *fac)
382{
383 char filename[PATH_MAX];
384 unsigned int filename_size = 0;
385 FILE *fd;
386 dprintf("%s\n", fac->name);
387
388 strcpy(filename, "ltt-facility-");
389 filename_size = strlen(filename);
390
391 strncat(filename, fac->name, PATH_MAX - filename_size);
392 filename_size = strlen(filename);
393
394 strncat(filename, ".h", PATH_MAX - filename_size);
395 filename_size = strlen(filename);
396
397
398 fd = fopen(filename, "w");
399 if(fd == NULL) {
400 printf("Error opening file %s for writing : %s\n",
401 filename, strerror(errno));
402 return errno;
403 }
404
405 /* Print file head */
406 print_log_header_head(fac, fd);
407
408 /* print named types in declaration order */
409 if(print_log_header_types(fac, fd)) return 1;
410
411 /* Print events */
412 if(print_log_header_events(fac, fd)) return 1;
413
414 /* Print file tail */
415 print_log_header_tail(fac, fd);
416
417
418 fclose(fd);
419
420 return 0;
421}
422
423
424/* ltt-facility-id-name.h : facility id.
425 * log_id_header */
426int print_id_header(facility_t *fac)
427{
428 char filename[PATH_MAX];
429 unsigned int filename_size = 0;
430 FILE *fd;
431 dprintf("%s\n", fac->name);
432
433 strcpy(filename, "ltt-facility-id-");
434 filename_size = strlen(filename);
435
436 strncat(filename, fac->name, PATH_MAX - filename_size);
437 filename_size = strlen(filename);
438
439 strncat(filename, ".h", PATH_MAX - filename_size);
440 filename_size = strlen(filename);
441
442
443 fd = fopen(filename, "w");
444 if(fd == NULL) {
445 printf("Error opening file %s for writing : %s\n",
446 filename, strerror(errno));
447 return errno;
448 }
449
450 fclose(fd);
451
452 return 0;
453}
454
455
456/* ltt-facility-loader-name.h : facility specific loader info.
457 * loader_header */
458int print_loader_header(facility_t *fac)
459{
460 char filename[PATH_MAX];
461 unsigned int filename_size = 0;
462 FILE *fd;
463 dprintf("%s\n", fac->name);
464
465 strcpy(filename, "ltt-facility-loader-");
466 filename_size = strlen(filename);
467
468 strncat(filename, fac->name, PATH_MAX - filename_size);
469 filename_size = strlen(filename);
470
471 strncat(filename, ".h", PATH_MAX - filename_size);
472 filename_size = strlen(filename);
473
474
475 fd = fopen(filename, "w");
476 if(fd == NULL) {
477 printf("Error opening file %s for writing : %s\n",
478 filename, strerror(errno));
479 return errno;
480 }
481
482 fclose(fd);
483
484 return 0;
485}
486
487/* ltt-facility-loader-name.c : generic faciilty loader
488 * loader_c */
489int print_loader_c(facility_t *fac)
490{
491 char filename[PATH_MAX];
492 unsigned int filename_size = 0;
493 FILE *fd;
494 dprintf("%s\n", fac->name);
495
496 strcpy(filename, "ltt-facility-loader-");
497 filename_size = strlen(filename);
498
499 strncat(filename, fac->name, PATH_MAX - filename_size);
500 filename_size = strlen(filename);
501
502 strncat(filename, ".c", PATH_MAX - filename_size);
503 filename_size = strlen(filename);
504
505
506 fd = fopen(filename, "w");
507 if(fd == NULL) {
508 printf("Error opening file %s for writing : %s\n",
509 filename, strerror(errno));
510 return errno;
511 }
512
513
514 fclose(fd);
515
516 return 0;
517}
518
519
520
92d82357 521/* open facility */
522/* code taken from ltt_facility_open in ltt/facility.c in lttv */
523
524/*****************************************************************************
525 *Function name
526 * ltt_facility_open : open facilities
527 *Input params
528 * pathname : the path name of the facility
529 *
530 * Open the facility corresponding to the right checksum.
531 *
532 *returns the facility on success, NULL on error.
533 ****************************************************************************/
534facility_t *ltt_facility_open(char * pathname)
535{
536 int ret = 0;
537 char *token;
538 parse_file_t in;
539 facility_t * fac = NULL;
540 unsigned long checksum;
541 char buffer[BUFFER_SIZE];
542 int generated = FALSE;
543
544 in.buffer = &(buffer[0]);
545 in.lineno = 0;
546 in.error = error_callback;
547 in.name = pathname;
548 in.unget = 0;
549
550 in.fp = fopen(in.name, "r");
551 if(in.fp == NULL) {
552 ret = 1;
553 goto open_error;
554 }
555
556 while(1){
557 token = getToken(&in);
558 if(in.type == ENDFILE) break;
559
560 if(generated) {
561 printf("More than one facility in the file. Only using the first one.\n");
562 break;
563 }
564
565 if(strcmp(token, "<")) in.error(&in,"not a facility file");
566 token = getName(&in);
567
568 if(strcmp("facility",token) == 0) {
569 fac = malloc(sizeof(facility_t));
570 fac->name = NULL;
571 fac->description = NULL;
572 sequence_init(&(fac->events));
573 table_init(&(fac->named_types));
574 sequence_init(&(fac->unnamed_types));
575
576 parseFacility(&in, fac);
577
578 //check if any namedType is not defined
579 checkNamedTypesImplemented(&fac->named_types);
580
581 generateChecksum(fac->name, &checksum, &fac->events);
582
583 generated = TRUE;
584 }
585 else {
586 printf("facility token was expected in file %s\n", in.name);
587 ret = 1;
588 goto parse_error;
589 }
590 }
591
592 parse_error:
593 fclose(in.fp);
594open_error:
595
596 if(!generated) {
597 printf("Cannot find facility %s\n", pathname);
598 fac = NULL;
599 }
600
601 return fac;
602}
603
604/* Close the facility */
605void ltt_facility_close(facility_t *fac)
606{
607 free(fac->name);
608 free(fac->capname);
609 free(fac->description);
610 freeEvents(&fac->events);
611 sequence_dispose(&fac->events);
612 freeNamedType(&fac->named_types);
613 table_dispose(&fac->named_types);
614 freeTypes(&fac->unnamed_types);
615 sequence_dispose(&fac->unnamed_types);
616 free(fac);
617}
618
619
620/* Show help */
621void show_help(int argc, char ** argv)
622{
623 printf("Genevent help : \n");
624 printf("\n");
625 printf("Use %s name.xml\n", argv[0]);
626 printf("to create :\n");
627 printf("ltt-facility-name.h\n");
628 printf("ltt-facility-id-name.h\n");
629 printf("ltt-facility-loader-name.h\n");
630 printf("ltt-facility-loader-name.c\n");
631 printf("In the current directory.\n");
632 printf("\n");
633}
634
635/* Parse program arguments */
636/* Return values :
637 * 0 : continue program
638 * -1 : stop program, return 0
639 * > 0 : stop program, return value as exit.
640 */
641int check_args(int argc, char **argv)
642{
643 if(argc < 2) {
644 printf("Not enough arguments\n");
645 show_help(argc, argv);
646 return EINVAL;
647 }
648
649 if(strcmp(argv[1], "-h") == 0) {
650 show_help(argc, argv);
651 return -1;
652 }
653
654 return 0;
655}
656
657int main(int argc, char **argv)
658{
659 int err = 0;
660 facility_t *fac;
661
662 err = check_args(argc, argv);
663 if(err > 0) return err;
664 else if(err < 0) return 0;
665
666 /* open the facility */
667 fac = ltt_facility_open(argv[1]);
668 if(fac == NULL) {
669 printf("Error opening file %s for reading : %s\n",
670 argv[1], strerror(errno));
671 return errno;
672 }
673
674 /* generate the output C files */
675
676
2d2d14a7 677 /* ltt-facility-name.h : main logging header.
678 * log_header */
679 err = print_log_header(fac);
680 if(err) return err;
92d82357 681
2d2d14a7 682 /* ltt-facility-id-name.h : facility id.
683 * log_id_header */
684 err = print_id_header(fac);
685 if(err) return err;
92d82357 686
2d2d14a7 687 /* ltt-facility-loader-name.h : facility specific loader info.
688 * loader_header */
689 err = print_loader_header(fac);
690 if(err) return err;
691
692 /* ltt-facility-loader-name.c : generic faciilty loader
693 * loader_c */
694 err = print_loader_c(fac);
695 if(err) return err;
92d82357 696
697 /* close the facility */
698 ltt_facility_close(fac);
699
700 return 0;
701}
702
703
This page took 0.049585 seconds and 4 git commands to generate.