X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=genevent%2Fgenevent.c;h=fb564597ed78ef4b707c32dcfe788a738861ca84;hb=0c4a454eaad85a4bc32142d43ce7d7cf9b919bb7;hp=14bc6ddd720d2b061ba74ad26e64cf8e8d25e85d;hpb=6d38759777e14cc3116fb7216b7037d183661a60;p=lttv.git diff --git a/genevent/genevent.c b/genevent/genevent.c index 14bc6ddd..fb564597 100644 --- a/genevent/genevent.c +++ b/genevent/genevent.c @@ -1,594 +1,3013 @@ -/* +/****************************************************************************** + * Genevent + * + * Event generator. XML to logging C code converter. + * + * Program parameters : + * ./genevent name.xml + * + * Will generate ltt-facility-name.h, ltt-facility-id-name.h + * ltt-facility-loader-name.c, ltt-facility-loader-name.h + * in the current directory. + * + * Supports : + * - C Alignment + * - C types : struct, union, enum, basic types. + * - Architectures : LP32, ILP32, ILP64, LLP64, LP64. + * + * Additionnal structures supported : + * - embedded variable size strings + * - embedded variable size arrays + * - embedded variable size sequences + * + * Notes : + * (1) + * enums are limited to integer type, as this is what is used in C. Note, + * however, that ISO/IEC 9899:TC2 specify that the type of enum can be char, + * unsigned int or int. This is implementation defined (compiler). That's why we + * add a check for sizeof enum. + * + * (2) + * Because of archtecture defined type sizes, we need to ask for ltt_align + * (which gives the alignment) by passing basic types, not their actual sizes. + * It's up to ltt_align to determine sizes of types. + * + * Note that, from + * http://www.usenix.org/publications/login/standards/10.data.html + * (Andrew Josey ) : + * + * Data Type LP32 ILP32 ILP64 LLP64 LP64 + * char 8 8 8 8 8 + * short 16 16 16 16 16 + * int32 32 + * int 16 32 64 32 32 + * long 32 32 64 32 64 + * long long (int64) 64 + * pointer 32 32 64 64 64 + * + * With these constraints : + * sizeof(char) <= sizeof(short) <= sizeof(int) + * <= sizeof(long) = sizeof(size_t) + * + * and therefore sizeof(long) <= sizeof(pointer) <= sizeof(size_t) + * + * Which means we only have to remember which is the biggest type in a structure + * to know the structure's alignment. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -genevent.c: Generate helper declarations and functions to trace events - from an event description file. +#include "genevent.h" +#include "parser.h" -Copyright (C) 2002, Xianxiu Yang -Copyright (C) 2002, Michel Dagenais - -This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* This program reads the ".event" event definitions input files - specified as command line arguments and generates corresponding - ".c" and ".h" files required to trace such events in the kernel. - - The program uses a very simple tokenizer, called from a hand written - recursive descent parser to fill a data structure describing the events. - The result is a sequence of events definitions which refer to type - definitions. - A table of named types is maintained to allow refering to types by name - when the same type is used at several places. Finally a sequence of - all types is maintained to facilitate the freeing of all type - information when the processing of an ".event" file is finished. */ +#define TRUE 1 +#define FALSE (!TRUE) -#include -#include -#include -#include -#include -#include +/* Debugging printf */ +#ifdef DEBUG +#define dprintf(...) \ + do {\ + printf(__FILE__ ",%u,%s: ",\ + __LINE__, __func__);\ + printf(__VA_ARGS__);\ + } while(0) +#else +#define dprintf(...) +#endif -#include "parser.h" -#include "genevent.h" +enum user_fct_types { USER_FCT_PROTO, USER_FCT_DECLARATION } ; + +/* Code printing */ -/* Named types may be referenced from anywhere */ +void print_tabs(unsigned int tabs, FILE *fd) +{ + for(unsigned int i = 0; itype_name != NULL) { + strncpy(basename, td->type_name, PATH_MAX); + basename_len = strlen(basename); + } else { + /* For a unnamed type, there must be a field name */ + if((basename_len != 0) + && (basename[basename_len-1] != '_') + && (field_name[0] != '\0')) { + strncat(basename, "_", PATH_MAX - basename_len); + basename_len = strlen(basename); + } + strncat(basename, field_name, PATH_MAX - basename_len); + } - in.buffer = buffer; - in.error = error_callback; - - for(i = 1 ; i < argc ; i++) { - in.lineno = 0; - in.name = allocAndCopy(argv[i]); - - in.fp = fopen(in.name, "r"); - if(!in.fp ){ - in.error(&in,"cannot open facility input file"); - } - - while(1){ - token = getToken(&in); - if(in.type == ENDFILE) break; - - if(strcmp(token, "<")) in.error(&in,"not a facility file"); - token = getName(&in); - - if(strcmp("facility",token) == 0) { - fac = memAlloc(sizeof(facility)); - fac->name = NULL; - fac->description = NULL; - sequence_init(&(fac->events)); - table_init(&(fac->named_types)); - sequence_init(&(fac->unnamed_types)); - - parseFacility(&in, fac); - - //check if any namedType is not defined - checkNamedTypesImplemented(&fac->named_types); - } - else in.error(&in,"facility token was expected"); - - generateFile(argv[i]); - - free(fac->name); - free(fac->description); - freeEvents(&fac->events); - sequence_dispose(&fac->events); - freeNamedType(&fac->named_types); - table_dispose(&fac->named_types); - freeTypes(&fac->unnamed_types); - sequence_dispose(&fac->unnamed_types); - free(fac); - } - - free(in.name); - fclose(in.fp); + switch(td->type) { + case INT_FIXED: + fprintf(fd, "%s", intOutputTypes[getSizeindex(td->size)]); + break; + case UINT_FIXED: + fprintf(fd, "%s", uintOutputTypes[getSizeindex(td->size)]); + break; + case CHAR: + fprintf(fd, "signed char"); + break; + case UCHAR: + fprintf(fd, "unsigned char"); + break; + case SHORT: + fprintf(fd, "short"); + break; + case USHORT: + fprintf(fd, "unsigned short"); + break; + case INT: + fprintf(fd, "int"); + break; + case UINT: + fprintf(fd, "unsigned int"); + break; + case FLOAT: + fprintf(fd, "%s", floatOutputTypes[getSizeindex(td->size)]); + break; + case POINTER: + fprintf(fd, "const void *"); + break; + case LONG: + fprintf(fd, "long"); + break; + case ULONG: + fprintf(fd, "unsigned long"); + break; + case SIZE_T: + fprintf(fd, "size_t"); + break; + case SSIZE_T: + fprintf(fd, "ssize_t"); + break; + case OFF_T: + fprintf(fd, "off_t"); + break; + case STRING: + fprintf(fd, "const char *"); + break; + case ENUM: + fprintf(fd, "enum lttng_%s", basename); + break; + case ARRAY: + fprintf(fd, "lttng_array_%s", basename); + break; + case SEQUENCE: + fprintf(fd, "lttng_sequence_%s", basename); + break; + case STRUCT: + fprintf(fd, "struct lttng_%s", basename); + break; + case UNION: + fprintf(fd, "union lttng_%s", basename); + break; + default: + printf("print_type : unknown type\n"); + return 1; + } - } - return 0; + return 0; } +/* Print logging function argument */ +int print_arg(type_descriptor_t * td, FILE *fd, unsigned int tabs, + char *nest_name, char *field_name) +{ + char basename[PATH_MAX]; + unsigned int basename_len = 0; + + strcpy(basename, nest_name); + basename_len = strlen(basename); + + /* For a named type, we use the type_name directly */ + if(td->type_name != NULL) { + strncpy(basename, td->type_name, PATH_MAX); + basename_len = strlen(basename); + } else { + /* For a unnamed type, there must be a field name */ + if((basename_len != 0) + && (basename[basename_len-1] != '_') + && (field_name[0] != '\0')) { + strncat(basename, "_", PATH_MAX - basename_len); + basename_len = strlen(basename); + } + strncat(basename, field_name, PATH_MAX - basename_len); + } -/***************************************************************************** - *Function name - * generateFile : generate .c and .h file - *Input Params - * name : name of event definition file - ****************************************************************************/ -void generateFile(char *name){ - char *loadName, *hName, *tmp, *tmp2; - FILE * lFp, *hFp; - int nbEvent; - unsigned long checksum=0; - - //remove .xml if it exists - tmp = &name[strlen(name)-4]; - if(strcmp(tmp, ".xml") == 0){ - *tmp = '\0'; - } + print_tabs(tabs, fd); + + switch(td->type) { + case INT_FIXED: + fprintf(fd, "%s", intOutputTypes[getSizeindex(td->size)]); + fprintf(fd, " lttng_param_%s", field_name); + break; + case UINT_FIXED: + fprintf(fd, "%s", uintOutputTypes[getSizeindex(td->size)]); + fprintf(fd, " lttng_param_%s", field_name); + break; + case CHAR: + fprintf(fd, "signed char"); + fprintf(fd, " lttng_param_%s", field_name); + break; + case UCHAR: + fprintf(fd, "unsigned char"); + fprintf(fd, " lttng_param_%s", field_name); + break; + case SHORT: + fprintf(fd, "short"); + fprintf(fd, " lttng_param_%s", field_name); + break; + case USHORT: + fprintf(fd, "unsigned short"); + fprintf(fd, " lttng_param_%s", field_name); + break; + case INT: + fprintf(fd, "int"); + fprintf(fd, " lttng_param_%s", field_name); + break; + case UINT: + fprintf(fd, "unsigned int"); + fprintf(fd, " lttng_param_%s", field_name); + break; + case FLOAT: + fprintf(fd, "%s", floatOutputTypes[getSizeindex(td->size)]); + fprintf(fd, " lttng_param_%s", field_name); + break; + case POINTER: + fprintf(fd, "const void *"); + fprintf(fd, " lttng_param_%s", field_name); + break; + case LONG: + fprintf(fd, "long"); + fprintf(fd, " lttng_param_%s", field_name); + break; + case ULONG: + fprintf(fd, "unsigned long"); + fprintf(fd, " lttng_param_%s", field_name); + break; + case SIZE_T: + fprintf(fd, "size_t"); + fprintf(fd, " lttng_param_%s", field_name); + break; + case SSIZE_T: + fprintf(fd, "ssize_t"); + fprintf(fd, " lttng_param_%s", field_name); + break; + case OFF_T: + fprintf(fd, "off_t"); + fprintf(fd, " lttng_param_%s", field_name); + break; + case STRING: + fprintf(fd, "const char *"); + fprintf(fd, " lttng_param_%s", field_name); + break; + case ENUM: + fprintf(fd, "enum lttng_%s", basename); + fprintf(fd, " lttng_param_%s", field_name); + break; + case ARRAY: + fprintf(fd, "lttng_array_%s", basename); + fprintf(fd, " lttng_param_%s", field_name); + break; + case SEQUENCE: + fprintf(fd, "lttng_sequence_%s *", basename); + fprintf(fd, " lttng_param_%s", field_name); + break; + case STRUCT: + fprintf(fd, "struct lttng_%s *", basename); + fprintf(fd, " lttng_param_%s", field_name); + break; + case UNION: + fprintf(fd, "union lttng_%s *", basename); + fprintf(fd, " lttng_param_%s", field_name); + break; + default: + printf("print_type : unknown type\n"); + return 1; + } - tmp = strrchr(name,'/'); - if(tmp){ - tmp++; - }else{ - tmp = name; - } + return 0; +} - loadName = appendString("ltt-facility-loader-", tmp); - tmp2 = appendString(loadName,".h"); - free(loadName); - loadName = tmp2; - hName = appendString("ltt-facility-", tmp); - tmp2 = appendString(hName,".h"); - free(hName); - hName = tmp2; - lFp = fopen(loadName,"w"); - if(!lFp){ - printf("Cannot open the file : %s\n",loadName); - exit(1); - } - hFp = fopen(hName,"w"); - if(!hFp){ - printf("Cannot open the file : %s\n",hName); - exit(1); +/* Does the type has a fixed size ? (as know from the compiler) + * + * 1 : fixed size + * 0 : variable length + */ +int has_type_fixed_size(type_descriptor_t *td) +{ + switch(td->type) { + case INT_FIXED: + case UINT_FIXED: + case CHAR: + case UCHAR: + case SHORT: + case USHORT: + case INT: + case UINT: + case FLOAT: + case POINTER: + case LONG: + case ULONG: + case SIZE_T: + case SSIZE_T: + case OFF_T: + case ENUM: + case UNION: /* The union must have fixed size children. Must be checked by + the parser */ + return 1; + break; + case STRING: + case SEQUENCE: + return 0; + break; + case STRUCT: + { + int has_type_fixed = 0; + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(td->fields.array[i]); + type_descriptor_t *type = field->type; + + has_type_fixed = has_type_fixed_size(type); + if(!has_type_fixed) return 0; + } + return 1; + } + break; + case ARRAY: + assert(td->size >= 0); + return has_type_fixed_size(((field_t*)td->fields.array[0])->type); + break; + case NONE: + printf("There is a type defined to NONE : bad.\n"); + assert(0); + break; + } + return 0; //make gcc happy. +} + + + + + +/* print type declaration. + * + * Copied from construct_types_and_fields in LTTV facility.c */ + +int print_type_declaration(type_descriptor_t * td, FILE *fd, unsigned int tabs, + char *nest_name, char *field_name) +{ + char basename[PATH_MAX]; + unsigned int basename_len = 0; + + if(td->custom_write) return 0; /* Does print custom type */ + + strncpy(basename, nest_name, PATH_MAX); + basename_len = strlen(basename); + + /* For a named type, we use the type_name directly */ + if(td->type_name != NULL) { + strncpy(basename, td->type_name, PATH_MAX); + basename_len = strlen(basename); + } else { + /* For a unnamed type, there must be a field name, except for + * the array. */ + if((basename_len != 0) + && (basename[basename_len-1] != '_' + && (field_name[0] != '\0'))) { + strncat(basename, "_", PATH_MAX - basename_len); + basename_len = strlen(basename); + } + strncat(basename, field_name, PATH_MAX - basename_len); + } + + switch(td->type) { + case ENUM: + fprintf(fd, "enum lttng_%s", basename); + fprintf(fd, " {\n"); + for(unsigned int i=0;ilabels.position;i++){ + print_tabs(1, fd); + fprintf(fd, "LTTNG_%s = %d", ((char*)td->labels.array[i]), + (*(int*)td->labels_values.array[i])); + fprintf(fd, ",\n"); + } + fprintf(fd, "};\n"); + fprintf(fd, "\n"); + break; + + case ARRAY: + dprintf("%s\n", basename); + assert(td->size >= 0); + if(((field_t*)td->fields.array[0])->type->type_name == NULL) { + /* Not a named nested type : we must print its declaration first */ + if(print_type_declaration(((field_t*)td->fields.array[0])->type, + fd, 0, basename, "")) return 1; + } + fprintf(fd, "#define LTTNG_ARRAY_SIZE_%s %zu\n", basename, + td->size); + fprintf(fd, "typedef "); + if(print_type(((field_t*)td->fields.array[0])->type, + fd, tabs, basename, "")) return 1; + fprintf(fd, " lttng_array_%s[LTTNG_ARRAY_SIZE_%s];\n", basename, + basename); + fprintf(fd, "\n"); + break; + case SEQUENCE: + /* We assume that the sequence length type does not need to be declared. + */ + if(((field_t*)td->fields.array[1])->type->type_name == NULL) { + /* Not a named nested type : we must print its declaration first */ + if(print_type_declaration(((field_t*)td->fields.array[1])->type, + fd, 0, basename, "")) return 1; + } + fprintf(fd, "typedef struct lttng_sequence_%s lttng_sequence_%s;\n", + basename, + basename); + fprintf(fd, "struct lttng_sequence_%s", basename); + fprintf(fd, " {\n"); + print_tabs(1, fd); + if(print_type(((field_t*)td->fields.array[0])->type, + fd, tabs, basename, "")) return 1; + fprintf(fd, " len;\n"); + print_tabs(1, fd); + fprintf(fd, "const "); + if(print_type(((field_t*)td->fields.array[1])->type, + fd, tabs, basename, "")) return 1; + fprintf(fd, " *array;\n"); + fprintf(fd, "};\n"); /* We do not LTT_ALIGN, because we never copy + it to the buffer directly. */ + fprintf(fd, "\n"); + break; + + case STRUCT: + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(td->fields.array[i]); + type_descriptor_t *type = field->type; + if(type->type_name == NULL) { + /* Not a named nested type : we must print its declaration first */ + if(print_type_declaration(type, + fd, 0, basename, field->name)) return 1; + } + } + fprintf(fd, "struct lttng_%s", basename); + fprintf(fd, " {\n"); + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(td->fields.array[i]); + type_descriptor_t *type = field->type; + print_tabs(1, fd); + if(print_type(type, fd, tabs, basename, field->name)) return 1; + fprintf(fd, " "); + fprintf(fd, "%s", field->name); + fprintf(fd, ";\n"); + } + fprintf(fd, "} LTT_ALIGN;\n"); + fprintf(fd, "\n"); + break; + case UNION: + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(td->fields.array[i]); + type_descriptor_t *type = field->type; + if(type->type_name == NULL) { + /* Not a named nested type : we must print its declaration first */ + if(print_type_declaration(type, + fd, 0, basename, field->name)) return 1; + } + } + fprintf(fd, "union lttng_%s", basename); + fprintf(fd, " {\n"); + for(unsigned i=0;ifields.position;i++){ + field_t *field = (field_t*)(td->fields.array[i]); + type_descriptor_t *type = field->type; + print_tabs(1, fd); + if(print_type(type, fd, tabs, basename, field->name)) return 1; + fprintf(fd, " "); + fprintf(fd, "%s", field->name); + fprintf(fd, ";\n"); + } + fprintf(fd, "} LTT_ALIGN;\n"); + fprintf(fd, "\n"); + break; + default: + dprintf("print_type_declaration : unknown type or nothing to declare.\n"); + break; + } + + return 0; +} + + +/* print type alignment. + * + * Copied from construct_types_and_fields in LTTV facility.c + * + * basename is the name which identifies the type (along with a prefix + * (possibly)). */ + +int print_type_alignment(type_descriptor_t * td, FILE *fd, unsigned int tabs, + char *nest_name, char *field_name, char *obj_prefix) +{ + char basename[PATH_MAX]; + unsigned int basename_len = 0; + + strncpy(basename, nest_name, PATH_MAX); + basename_len = strlen(basename); + + /* For a named type, we use the type_name directly */ + if(td->type_name != NULL) { + strncpy(basename, td->type_name, PATH_MAX); + basename_len = strlen(basename); + } else { + /* For a unnamed type, there must be a field name, except for + * the array. */ + if((basename_len != 0) + && (basename[basename_len-1] != '_' + && field_name != NULL + && (field_name[0] != '\0'))) { + strncat(basename, "_", PATH_MAX - basename_len); + basename_len = strlen(basename); + } + if(field_name != NULL) + strncat(basename, field_name, PATH_MAX - basename_len); + } + + if(field_name[0] == '\0') { + /* We are in a write function : it's the obj that we must align. */ + switch(td->type) { + case SEQUENCE: + fprintf(fd, "lttng_get_alignment_sequence_%s(%s)", basename, + obj_prefix); + break; + case STRUCT: + fprintf(fd, "lttng_get_alignment_struct_%s(%s)", basename, + obj_prefix); + break; + case UNION: + fprintf(fd, "lttng_get_alignment_union_%s(%s)", basename, + obj_prefix); + break; + case ARRAY: + fprintf(fd, "lttng_get_alignment_array_%s(%s)", basename, + obj_prefix); + case STRING: + fprintf(fd, "sizeof(char)"); + break; + case INT_FIXED: + case UINT_FIXED: + case CHAR: + case UCHAR: + case SHORT: + case USHORT: + case INT: + case UINT: + case FLOAT: + case POINTER: + case LONG: + case ULONG: + case SIZE_T: + case SSIZE_T: + case OFF_T: + case ENUM: + fprintf(fd, "sizeof("); + if(print_type(td, fd, 0, basename, "")) return 1; + fprintf(fd, ")"); + break; + + default: + printf("error : type unexpected\n"); + return 1; + break; + } + } else { + + switch(td->type) { + case INT_FIXED: + case UINT_FIXED: + case CHAR: + case UCHAR: + case SHORT: + case USHORT: + case INT: + case UINT: + case FLOAT: + case POINTER: + case LONG: + case ULONG: + case SIZE_T: + case SSIZE_T: + case OFF_T: + case ENUM: + fprintf(fd, "sizeof("); + if(print_type(td, fd, 0, basename, "")) return 1; + fprintf(fd, ")"); + break; + case STRING: + fprintf(fd, "sizeof(char)"); + break; + case SEQUENCE: + fprintf(fd, "lttng_get_alignment_sequence_%s(&%s%s)", basename, + obj_prefix, field_name); + break; + case STRUCT: + fprintf(fd, "lttng_get_alignment_struct_%s(&%s%s)", basename, + obj_prefix, field_name); + break; + case UNION: + fprintf(fd, "lttng_get_alignment_union_%s(&%s%s)", basename, + obj_prefix, field_name); + break; + case ARRAY: + fprintf(fd, "lttng_get_alignment_array_%s(%s%s)", basename, + obj_prefix, field_name); + break; + case NONE: + printf("error : type NONE unexpected\n"); + return 1; + break; + } + } + + return 0; +} + +/* print type write. + * + * Copied from construct_types_and_fields in LTTV facility.c + * + * basename is the name which identifies the type (along with a prefix + * (possibly)). */ + +int print_type_write(type_descriptor_t * td, FILE *fd, unsigned int tabs, + char *nest_name, char *field_name, char *obj_prefix, int get_ptr) +{ + char basename[PATH_MAX]; + unsigned int basename_len = 0; + char get_ptr_char[2] = ""; + char custom[PATH_MAX] = ""; + + strncpy(basename, nest_name, PATH_MAX); + basename_len = strlen(basename); + + /* For a named type, we use the type_name directly */ + if(td->type_name != NULL) { + strncpy(basename, td->type_name, PATH_MAX); + basename_len = strlen(basename); + } else { + /* For a unnamed type, there must be a field name, except for + * the array. */ + if((basename_len != 0) + && (basename[basename_len-1] != '_' + && (field_name[0] != '\0'))) { + strncat(basename, "_", PATH_MAX - basename_len); + basename_len = strlen(basename); + } + strncat(basename, field_name, PATH_MAX - basename_len); + } + + if(get_ptr) { + strcpy(get_ptr_char, "&"); + } + + if(td->custom_write) { + strcpy(custom, "_custom"); + } + + switch(td->type) { + case INT_FIXED: + case UINT_FIXED: + case CHAR: + case UCHAR: + case SHORT: + case USHORT: + case INT: + case UINT: + case FLOAT: + case POINTER: + case LONG: + case ULONG: + case SIZE_T: + case SSIZE_T: + case OFF_T: + case ENUM: + print_tabs(tabs, fd); + fprintf(fd, "align = "); + if(print_type_alignment(td, fd, 0, basename, "", "obj")) return 1; + fprintf(fd, ";\n"); + fprintf(fd, "\n"); + print_tabs(tabs, fd); + fprintf(fd, "if (*len == 0) {\n"); + print_tabs(tabs+1, fd); + fprintf(fd, "*to += ltt_align(*to, align); /* align output */\n"); + print_tabs(tabs, fd); + fprintf(fd, "} else {\n"); + print_tabs(tabs+1, fd); + fprintf(fd, "*len += ltt_align(*to+*len, align); /* alignment, ok to do a memcpy of it */\n"); + print_tabs(tabs, fd); + fprintf(fd, "}\n"); + fprintf(fd, "\n"); + + print_tabs(tabs, fd); + fprintf(fd, "*len += "); + fprintf(fd, "sizeof("); + if(print_type(td, fd, 0, basename, "")) return 1; + fprintf(fd, ");\n"); + + break; + case STRING: + print_tabs(tabs, fd); + fprintf(fd, + "lttng_write%s_string_%s(buffer, to_base, to, from, len, %s%s);\n", + custom, basename, obj_prefix, field_name); + break; + case SEQUENCE: + print_tabs(tabs, fd); + fprintf(fd, + "lttng_write%s_sequence_%s(buffer, to_base, to, from, len, %s%s%s);", + custom, basename, get_ptr_char, obj_prefix, field_name); + break; + case STRUCT: + print_tabs(tabs, fd); + fprintf(fd, + "lttng_write%s_struct_%s(buffer, to_base, to, from, len, %s%s%s);", + custom, basename, get_ptr_char, obj_prefix, field_name); + break; + case UNION: + print_tabs(tabs, fd); + fprintf(fd, + "lttng_write%s_union_%s(buffer, to_base, to, from, len, %s%s%s);", + custom, basename, get_ptr_char, obj_prefix, field_name); + break; + case ARRAY: + print_tabs(tabs, fd); + fprintf(fd, + "lttng_write%s_array_%s(buffer, to_base, to, from, len, %s%s);", + custom, basename, obj_prefix, field_name); + break; + case NONE: + printf("Error : type NONE unexpected\n"); + return 1; + break; + } + + return 0; +} + +/* print need local vars ?. + * + * Copied from print_type_write + * + * Does the type_write call needs local size and from variables ? + * return value : 1 yes, 0 no. + */ + +int has_type_local(type_descriptor_t * td) +{ + switch(td->type) { + case INT_FIXED: + case UINT_FIXED: + case CHAR: + case UCHAR: + case SHORT: + case USHORT: + case INT: + case UINT: + case FLOAT: + case POINTER: + case LONG: + case ULONG: + case SIZE_T: + case SSIZE_T: + case OFF_T: + case ENUM: + return 1; + break; + case STRING: + case SEQUENCE: + case STRUCT: + case UNION: + case ARRAY: + return 0; + break; + case NONE: + printf("Error : type NONE unexpected\n"); + return 1; + break; + } + + return 0; +} + + + +/* print type alignment function. + * + * Copied from construct_types_and_fields in LTTV facility.c + * + * basename is the name which identifies the type (along with a prefix + * (possibly)). */ + +int print_type_alignment_fct(type_descriptor_t * td, FILE *fd, + unsigned int tabs, + char *nest_name, char *field_name) +{ + char basename[PATH_MAX]; + unsigned int basename_len = 0; + + if(td->custom_write) return 0; /* Does print custom type */ + + strncpy(basename, nest_name, PATH_MAX); + basename_len = strlen(basename); + + /* For a named type, we use the type_name directly */ + if(td->type_name != NULL) { + strncpy(basename, td->type_name, PATH_MAX); + basename_len = strlen(basename); + } else { + /* For a unnamed type, there must be a field name, except for + * the array. */ + if((basename_len != 0) + && (basename[basename_len-1] != '_' + && (field_name[0] != '\0'))) { + strncat(basename, "_", PATH_MAX - basename_len); + basename_len = strlen(basename); + } + strncat(basename, field_name, PATH_MAX - basename_len); + } + + switch(td->type) { + case SEQUENCE: + if(((field_t*)td->fields.array[1])->type->type_name == NULL) { + /* Not a named nested type : we must print its align fct */ + if(print_type_alignment_fct(((field_t*)td->fields.array[1])->type, fd, + 0, basename, "")) return 1; + } + /* Function header */ + fprintf(fd, "static inline size_t lttng_get_alignment_sequence_%s(\n", + basename); + print_tabs(2, fd); + if(print_type(td, fd, 0, basename, "")) return 1; + fprintf(fd, " *obj)\n"); + fprintf(fd, "{\n"); + print_tabs(1, fd); + fprintf(fd, "size_t align=0, localign;"); + fprintf(fd, "\n"); + print_tabs(1, fd); + fprintf(fd, "localign = "); + if(print_type_alignment(((field_t*)td->fields.array[0])->type, + fd, 0, basename, "len", "obj->")) return 1; + fprintf(fd, ";\n"); + print_tabs(1, fd); + fprintf(fd, "align = max(align, localign);\n"); + fprintf(fd, "\n"); + print_tabs(1, fd); + fprintf(fd, "localign = "); + if(print_type_alignment(((field_t*)td->fields.array[1])->type, + fd, 0, basename, "array[0]", "obj->")) return 1; + fprintf(fd, ";\n"); + print_tabs(1, fd); + fprintf(fd, "align = max(align, localign);\n"); + fprintf(fd, "\n"); + print_tabs(1, fd); + fprintf(fd, "return align;\n"); + break; + case STRUCT: + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(td->fields.array[i]); + type_descriptor_t *type = field->type; + if(type->type_name == NULL) { + /* Not a named nested type : we must print its align fct */ + if(print_type_alignment_fct(type, fd, + 0, basename, field->name)) return 1; + } + } + /* Function header */ + fprintf(fd, "static inline size_t lttng_get_alignment_struct_%s(\n", + basename); + print_tabs(2, fd); + if(print_type(td, fd, 0, basename, "")) return 1; + fprintf(fd, " *obj)\n"); + fprintf(fd, "{\n"); + print_tabs(1, fd); + fprintf(fd, "size_t align=0, localign;"); + fprintf(fd, "\n"); + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(td->fields.array[i]); + type_descriptor_t *type = field->type; + print_tabs(1, fd); + fprintf(fd, "localign = "); + if(print_type_alignment(type, fd, 0, basename, field->name, "obj->")) + return 1; + fprintf(fd, ";\n"); + print_tabs(1, fd); + fprintf(fd, "align = max(align, localign);\n"); + fprintf(fd, "\n"); + } + print_tabs(1, fd); + fprintf(fd, "return align;\n"); + + break; + case UNION: + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(td->fields.array[i]); + type_descriptor_t *type = field->type; + if(type->type_name == NULL) { + /* Not a named nested type : we must print its align fct */ + if(print_type_alignment_fct(type, fd, + 0, basename, field->name)) return 1; + } + } + /* Function header */ + fprintf(fd, "static inline size_t lttng_get_alignment_union_%s(\n", + basename); + print_tabs(2, fd); + if(print_type(td, fd, 0, basename, "")) return 1; + fprintf(fd, " *obj)\n"); + fprintf(fd, "{\n"); + print_tabs(1, fd); + fprintf(fd, "size_t align=0, localign;"); + fprintf(fd, "\n"); + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(td->fields.array[i]); + type_descriptor_t *type = field->type; + print_tabs(1, fd); + fprintf(fd, "localign = "); + if(print_type_alignment(type, fd, 0, basename, field->name, "obj->")) + return 1; + fprintf(fd, ";\n"); + print_tabs(1, fd); + fprintf(fd, "align = max(align, localign);\n"); + fprintf(fd, "\n"); + } + print_tabs(1, fd); + fprintf(fd, "return align;\n"); + + break; + case ARRAY: + if(((field_t*)td->fields.array[0])->type->type_name == NULL) { + /* Not a named nested type : we must print its align fct */ + if(print_type_alignment_fct(((field_t*)td->fields.array[0])->type, fd, + 0, basename, "")) return 1; + } + /* Function header */ + fprintf(fd, "static inline size_t lttng_get_alignment_array_%s(\n", + basename); + print_tabs(2, fd); + if(print_type(td, fd, 0, basename, "")) return 1; + fprintf(fd, " obj)\n"); + fprintf(fd, "{\n"); + print_tabs(1, fd); + fprintf(fd, "return \n"); + if(print_type_alignment(((field_t*)td->fields.array[0])->type, + fd, 0, basename, "", "obj[0]")) + return 1; + fprintf(fd, ";\n"); + break; + default: + dprintf("print_type_alignment_fct : type has no alignment function.\n"); + return 0; + break; + } + + + /* Function footer */ + fprintf(fd, "}\n"); + fprintf(fd, "\n"); + + return 0; +} + +/* print type write function. + * + * Copied from construct_types_and_fields in LTTV facility.c + * + * basename is the name which identifies the type (along with a prefix + * (possibly)). */ + +int print_type_write_fct(type_descriptor_t * td, FILE *fd, unsigned int tabs, + char *nest_name, char *field_name) +{ + char basename[PATH_MAX]; + unsigned int basename_len = 0; + + if(td->custom_write) return 0; /* Does print custom type */ + + strncpy(basename, nest_name, PATH_MAX); + basename_len = strlen(basename); + + /* For a named type, we use the type_name directly */ + if(td->type_name != NULL) { + strncpy(basename, td->type_name, PATH_MAX); + basename_len = strlen(basename); + } else { + /* For a unnamed type, there must be a field name, except for + * the array. */ + if((basename_len != 0) + && (basename[basename_len-1] != '_' + && (field_name[0] != '\0'))) { + strncat(basename, "_", PATH_MAX - basename_len); + basename_len = strlen(basename); + } + strncat(basename, field_name, PATH_MAX - basename_len); + } + + switch(td->type) { + case SEQUENCE: + if(((field_t*)td->fields.array[1])->type->type_name == NULL) { + /* Not a named nested type : we must print its write fct */ + if(print_type_write_fct(((field_t*)td->fields.array[1])->type, fd, + 0, basename, "")) return 1; + } + break; + case STRUCT: + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(td->fields.array[i]); + type_descriptor_t *type = field->type; + if(type->type_name == NULL) { + /* Not a named nested type : we must print its write fct */ + if(print_type_write_fct(type, fd, + 0, basename, field->name)) return 1; + } + } + break; + case UNION: + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(td->fields.array[i]); + type_descriptor_t *type = field->type; + if(type->type_name == NULL) { + /* Not a named nested type : we must print its write fct */ + if(print_type_write_fct(type, fd, + 0, basename, field->name)) return 1; + } + } + break; + case ARRAY: + if(((field_t*)td->fields.array[0])->type->type_name == NULL) { + /* Not a named nested type : we must print its write fct */ + if(print_type_write_fct(((field_t*)td->fields.array[0])->type, fd, + 0, basename, "")) return 1; + } + break; + case STRING: + break; + default: + dprintf("print_type_write_fct : type has no write function.\n"); + return 0; + break; + } + + /* Print header */ + switch(td->type) { + case SEQUENCE: + fprintf(fd, "static inline void lttng_write_sequence_%s(\n", + basename); + break; + case STRUCT: + fprintf(fd, "static inline void lttng_write_struct_%s(\n", basename); + break; + case UNION: + fprintf(fd, "static inline void lttng_write_union_%s(\n", basename); + break; + case ARRAY: + fprintf(fd, "static inline void lttng_write_array_%s(\n", basename); + break; + case STRING: + fprintf(fd, "static inline void lttng_write_string_%s(\n", basename); + break; + default: + printf("print_type_write_fct : type has no write function.\n"); + break; + } + + print_tabs(2, fd); + fprintf(fd, "char *buffer,\n"); + print_tabs(2, fd); + fprintf(fd, "size_t *to_base,\n"); + print_tabs(2, fd); + fprintf(fd, "size_t *to,\n"); + print_tabs(2, fd); + fprintf(fd, "const char **from,\n"); + print_tabs(2, fd); + fprintf(fd, "size_t *len,\n"); + print_tabs(2, fd); + if(print_type(td, fd, 0, basename, "")) return 1; + + switch(td->type) { + case SEQUENCE: + fprintf(fd, " *obj)\n"); + break; + case STRUCT: + fprintf(fd, " *obj)\n"); + break; + case UNION: + fprintf(fd, " *obj)\n"); + break; + case ARRAY: + fprintf(fd, " obj)\n"); + break; + case STRING: + fprintf(fd, " obj)\n"); + break; + default: + printf("print_type_write_fct : type has no write function.\n"); + break; + } + + fprintf(fd, "{\n"); + + switch(td->type) { + case STRING: + print_tabs(1, fd); + fprintf(fd, "size_t size;\n"); + break; + default: + break; + } + + print_tabs(1, fd); + fprintf(fd, "size_t align;\n"); + fprintf(fd, "\n"); + + switch(td->type) { + case SEQUENCE: + case STRING: + print_tabs(1, fd); + fprintf(fd, "/* Flush pending memcpy */\n"); + print_tabs(1, fd); + fprintf(fd, "if (*len != 0) {\n"); + print_tabs(2, fd); + fprintf(fd, "if (buffer != NULL)\n"); + print_tabs(3, fd); + fprintf(fd, "memcpy(buffer+*to_base+*to, *from, *len);\n"); + print_tabs(1, fd); + fprintf(fd, "}\n"); + print_tabs(1, fd); + fprintf(fd, "*to += *len;\n"); + print_tabs(1, fd); + fprintf(fd, "*len = 0;\n"); + fprintf(fd, "\n"); + break; + case STRUCT: + case UNION: + case ARRAY: + break; + default: + printf("print_type_write_fct : type has no write function.\n"); + break; + } + + print_tabs(1, fd); + fprintf(fd, "align = "); + if(print_type_alignment(td, fd, 0, basename, "", "obj")) return 1; + fprintf(fd, ";\n"); + fprintf(fd, "\n"); + print_tabs(1, fd); + fprintf(fd, "if (*len == 0) {\n"); + print_tabs(2, fd); + fprintf(fd, "*to += ltt_align(*to, align); /* align output */\n"); + print_tabs(1, fd); + fprintf(fd, "} else {\n"); + print_tabs(2, fd); + fprintf(fd, "*len += ltt_align(*to+*len, align); /* alignment, ok to do a memcpy of it */\n"); + print_tabs(1, fd); + fprintf(fd, "}\n"); + fprintf(fd, "\n"); + + /* First, check if the type has a fixed size. If it is the case, then the size + * to write is know by the compiler : simply use a sizeof() */ + if(has_type_fixed_size(td)) { + print_tabs(1, fd); + fprintf(fd, "/* Contains only fixed size fields : use compiler sizeof() */\n"); + fprintf(fd, "\n"); + print_tabs(1, fd); + fprintf(fd, "*len += sizeof("); + if(print_type(td, fd, 0, basename, field_name)) return 1; + fprintf(fd, ");\n"); + } else { + /* The type contains nested variable size subtypes : + * we must write field by field. */ + print_tabs(1, fd); + fprintf(fd, "/* Contains variable sized fields : must explode the structure */\n"); + fprintf(fd, "\n"); + + switch(td->type) { + case SEQUENCE: + print_tabs(1, fd); + fprintf(fd, "/* Copy members */\n"); +// print_tabs(1, fd); +// fprintf(fd, "size = sizeof(\n"); + if(print_type_write(((field_t*)td->fields.array[0])->type, + fd, 1, basename, "len", "obj->", 1)) return 1; + fprintf(fd, "\n"); +// fprintf(fd, ");\n"); +// print_tabs(1, fd); +// fprintf(fd, "*to += ltt_align(*to, size);\n"); + print_tabs(1, fd); + fprintf(fd, "if (buffer != NULL)\n"); + print_tabs(2, fd); + fprintf(fd, "memcpy(buffer+*to_base+*to, &obj->len, *len);\n"); + print_tabs(1, fd); + fprintf(fd, "*to += *len;\n"); + print_tabs(1, fd); + fprintf(fd, "*len = 0;\n"); + fprintf(fd, "\n"); + + /* Write the child : varlen child or not ? */ + if(has_type_fixed_size(((field_t*)td->fields.array[1])->type)) { + /* Fixed size len child : use a multiplication of its size */ +// print_tabs(1, fd); +// fprintf(fd, "size = sizeof(\n"); + + //print_tabs(1, fd); + /* We know that *len does not contain alignment because of the + * previous align output. len is always 0 here. */ + if(print_type_write(((field_t*)td->fields.array[1])->type, + fd, 1, basename, "array[0]", "obj->", 1)) + return 1; +// fprintf(fd, ");\n"); + fprintf(fd, "\n"); + print_tabs(1, fd); + fprintf(fd, "*len = obj->len * (*len);\n"); + print_tabs(1, fd); + fprintf(fd, "if (buffer != NULL)\n"); + print_tabs(2, fd); + fprintf(fd, "memcpy(buffer+*to_base+*to, obj->array, *len);\n"); + print_tabs(1, fd); + fprintf(fd, "*to += *len;\n"); + print_tabs(1, fd); + fprintf(fd, "*len = 0;\n"); + fprintf(fd, "\n"); + } else { + print_tabs(1, fd); + fprintf(fd, "/* Variable length child : iter. */\n"); + print_tabs(1, fd); + fprintf(fd, "for (unsigned int i = 0; i < obj->len; i++) {\n"); + if(print_type_write(((field_t*)td->fields.array[1])->type, + fd, 2, basename, "array[i]", "obj->", 1)) return 1; + print_tabs(1, fd); + fprintf(fd, "}\n"); + } + fprintf(fd, "\n"); + print_tabs(1, fd); + fprintf(fd, "/* Realign the *to_base on arch size, set *to to 0 */\n"); + print_tabs(1, fd); + fprintf(fd, "*to += ltt_align(*to, sizeof(void *));\n"); + print_tabs(1, fd); + fprintf(fd, "*to_base = *to_base+*to;\n"); + print_tabs(1, fd); + fprintf(fd, "*to = 0;\n"); + fprintf(fd, "\n"); + print_tabs(1, fd); + fprintf(fd, "/* Put source *from just after the C sequence */\n"); + print_tabs(1, fd); + fprintf(fd, "*from = (const char*)(obj+1);\n"); + break; + case STRING: + print_tabs(1, fd); + fprintf(fd, "size = strlen(obj) + 1; /* Include final NULL char. */\n"); + print_tabs(1, fd); + fprintf(fd, "if (buffer != NULL)\n"); + print_tabs(2, fd); + fprintf(fd, "memcpy(buffer+*to_base+*to, obj, size);\n"); + print_tabs(1, fd); + fprintf(fd, "*to += size;\n"); + fprintf(fd, "\n"); + print_tabs(1, fd); + fprintf(fd, "/* Realign the *to_base on arch size, set *to to 0 */\n"); + print_tabs(1, fd); + fprintf(fd, "*to += ltt_align(*to, sizeof(void *));\n"); + print_tabs(1, fd); + fprintf(fd, "*to_base = *to_base+*to;\n"); + print_tabs(1, fd); + fprintf(fd, "*to = 0;\n"); + fprintf(fd, "\n"); + print_tabs(1, fd); + fprintf(fd, "/* Put source *from just after the C string */\n"); + print_tabs(1, fd); + fprintf(fd, "*from += size;\n"); + break; + case STRUCT: + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(td->fields.array[i]); + type_descriptor_t *type = field->type; + if(print_type_write(type, + fd, 1, basename, field->name, "obj->", 1)) return 1; + fprintf(fd, "\n"); + } + break; + case UNION: + printf("ERROR : A union CANNOT contain a variable size child.\n"); + return 1; + break; + case ARRAY: + /* Write the child : varlen child or not ? */ + if(has_type_fixed_size(((field_t*)td->fields.array[0])->type)) { + /* Error : if an array has a variable size, then its child must also + * have a variable size. */ + assert(0); + } else { + print_tabs(1, fd); + fprintf(fd, "/* Variable length child : iter. */\n"); + print_tabs(1, fd); + fprintf(fd, "for (unsigned int i = 0; i < LTTNG_ARRAY_SIZE_%s; i++) {\n", basename); + if(print_type_write(((field_t*)td->fields.array[0])->type, + fd, 2, basename, "", "obj->array[i]", 1)) return 1; + print_tabs(1, fd); + fprintf(fd, "}\n"); + } + break; + default: + printf("print_type_write_fct : type has no write function.\n"); + break; + } + + + } + + + /* Function footer */ + fprintf(fd, "}\n"); + fprintf(fd, "\n"); + return 0; +} + + + +/* Print the logging function of an event. This is the core of genevent */ +int print_event_logging_function(char *basename, facility_t *fac, + event_t *event, FILE *fd) +{ + fprintf(fd, "static inline void trace_%s(\n", basename); + int has_argument = 0; + int has_type_fixed = 0; + + /* Does it support per trace tracing ? */ + if(event->per_trace) { + print_tabs(2, fd); + fprintf(fd, "struct ltt_trace_struct *dest_trace"); + has_argument = 1; } - free(loadName); - free(hName); - - generateChecksum(fac->name, &checksum, &(fac->events)); - - /* generate .h file, event enumeration then structures and functions */ - fprintf(hFp, "#ifndef _LTT_FACILITY_%s_H_\n",fac->capname); - fprintf(hFp, "#define _LTT_FACILITY_%s_H_\n\n",fac->capname); - generateEnumEvent(hFp, fac->name, &nbEvent, checksum); - generateTypeDefs(hFp); - generateStructFunc(hFp, fac->name,checksum); - fprintf(hFp, "#endif //_LTT_FACILITY_%s_H_\n",fac->capname); - - /* generate .h file, calls to register the facility at init time */ - fprintf(lFp, "#ifndef _LTT_FACILITY_LOADER_%s_H_\n",fac->capname); - fprintf(lFp, "#define _LTT_FACILITY_LOADER_%s_H_\n\n",fac->capname); - generateLoaderfile(lFp,fac->name,nbEvent,checksum); - fprintf(lFp, "#endif //_LTT_FACILITY_LOADER_%s_H_\n",fac->capname); - - fclose(hFp); - fclose(lFp); + /* Does it support per tracefile tracing ? */ + if(event->per_tracefile) { + if(has_argument) { + fprintf(fd, ","); + fprintf(fd, "\n"); + } + fprintf(fd, "unsigned int tracefile_index"); + has_argument = 1; + } + + for(unsigned int j = 0; j < event->fields.position; j++) { + /* For each field, print the function argument */ + field_t *f = (field_t*)event->fields.array[j]; + type_descriptor_t *t = f->type; + if(has_argument) { + fprintf(fd, ","); + fprintf(fd, "\n"); + } + if(print_arg(t, fd, 2, basename, f->name)) return 1; + has_argument = 1; + } + if(!has_argument) { + print_tabs(2, fd); + fprintf(fd, "void"); + } + fprintf(fd,")\n"); +#if 0 + fprintf(fd, + "#if (!defined(CONFIG_LTT) || (!defined(CONFIG_LTT_FACILITY_%s) && !defined(CONFIG_LTT_FACILITY_%s_MODULE)))\n", + fac->capname, fac->capname); + fprintf(fd, "{\n"); + fprintf(fd, "}\n"); + fprintf(fd,"#else\n"); +#endif //0 + fprintf(fd, "{\n"); + /* Print the function variables */ + print_tabs(1, fd); + fprintf(fd, "unsigned int index;\n"); + print_tabs(1, fd); + fprintf(fd, "struct ltt_channel_struct *channel;\n"); + print_tabs(1, fd); + fprintf(fd, "struct ltt_trace_struct *trace;\n"); + print_tabs(1, fd); + fprintf(fd, "void *transport_data;\n"); + print_tabs(1, fd); + fprintf(fd, "char *buffer = NULL;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t real_to_base = 0; /* The buffer is allocated on arch_size alignment */\n"); + print_tabs(1, fd); + fprintf(fd, "size_t *to_base = &real_to_base;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t real_to = 0;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t *to = &real_to;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t real_len = 0;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t *len = &real_len;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t reserve_size;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t slot_size;\n"); + print_tabs(1, fd); + + if(event->fields.position > 0) { + for(unsigned int i=0;ifields.position;i++){ + /* Search for at least one child with fixed size. It means + * we need local variables.*/ + field_t *field = (field_t*)(event->fields.array[i]); + type_descriptor_t *type = field->type; + has_type_fixed = has_type_local(type); + if(has_type_fixed) break; + } + + if(has_type_fixed) { + fprintf(fd, "size_t align;\n"); + print_tabs(1, fd); + } + + fprintf(fd, "const char *real_from;\n"); + print_tabs(1, fd); + fprintf(fd, "const char **from = &real_from;\n"); + print_tabs(1, fd); + } + fprintf(fd, "u64 tsc;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t before_hdr_pad, after_hdr_pad, header_size;\n"); + fprintf(fd, "\n"); + + print_tabs(1, fd); + fprintf(fd, "if (ltt_traces.num_active_traces == 0)\n"); + print_tabs(2, fd); + fprintf(fd, "return;\n"); + fprintf(fd, "\n"); + + /* Calculate event variable len + event data alignment offset. + * Assume that the padding for alignment starts at a void* + * address. + * This excludes the header size and alignment. */ + + print_tabs(1, fd); + fprintf(fd, "/* For each field, calculate the field size. */\n"); + print_tabs(1, fd); + fprintf(fd, "/* size = *to_base + *to + *len */\n"); + print_tabs(1, fd); + fprintf(fd, "/* Assume that the padding for alignment starts at a\n"); + print_tabs(1, fd); + fprintf(fd, " * sizeof(void *) address. */\n"); + fprintf(fd, "\n"); + + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(event->fields.array[i]); + type_descriptor_t *type = field->type; + /* Set from */ + print_tabs(1, fd); + switch(type->type) { + case SEQUENCE: + case UNION: + case ARRAY: + case STRUCT: + case STRING: + fprintf(fd, "*from = (const char*)lttng_param_%s;\n", field->name); + break; + default: + fprintf(fd, "*from = (const char*)<tng_param_%s;\n", field->name); + break; + } + + if(print_type_write(type, + fd, 1, basename, field->name, "lttng_param_", 0)) return 1; + fprintf(fd, "\n"); + } + print_tabs(1, fd); + fprintf(fd, "reserve_size = *to_base + *to + *len;\n"); + + /* Take locks : make sure the trace does not vanish while we write on + * it. A simple preemption disabling is enough (using rcu traces). */ + print_tabs(1, fd); + fprintf(fd, "preempt_disable();\n"); + print_tabs(1, fd); + fprintf(fd, "ltt_nesting[smp_processor_id()]++;\n"); + + /* Get facility index */ + + if(event->per_tracefile) { + print_tabs(1, fd); + fprintf(fd, "index = tracefile_index;\n"); + } else { + print_tabs(1, fd); + fprintf(fd, + "index = ltt_get_index_from_facility_%s(" \ + "\t\t\t\t\t\tevent_%s_%s);\n", + fac->name, fac->name, event->name); + } + fprintf(fd,"\n"); + + + /* For each trace */ + print_tabs(1, fd); + fprintf(fd, "list_for_each_entry_rcu(trace, <t_traces.head, list) {\n"); + print_tabs(2, fd); + fprintf(fd, "if (!trace->active)\n"); + print_tabs(3, fd); + fprintf(fd, "continue;\n\n"); + + if(event->per_trace) { + print_tabs(2, fd); + fprintf(fd, "if (dest_trace != trace)\n"); + print_tabs(3, fd); + fprintf(fd, "continue;\n\n"); + } + + print_tabs(2, fd); + fprintf(fd, "channel = ltt_get_channel_from_index(trace, index);\n"); + fprintf(fd, "\n"); + + + /* Relay reserve */ + /* If error, increment event lost counter (done by ltt_reserve_slot) and + * return */ + print_tabs(2, fd); + fprintf(fd, "slot_size = 0;\n"); + print_tabs(2, fd); + fprintf(fd, "buffer = ltt_reserve_slot(trace, channel, &transport_data,\n"); + print_tabs(3, fd); + fprintf(fd, "reserve_size, &slot_size, &tsc,\n"); + print_tabs(3, fd); + fprintf(fd, "&before_hdr_pad, &after_hdr_pad, &header_size);\n"); + /* If error, return */ + print_tabs(2, fd); + fprintf(fd, "if (!buffer)\n"); + print_tabs(3, fd); + fprintf(fd, "continue; /* buffer full */\n\n"); + //print_tabs(2, fd); + // for DEBUG only + // fprintf(fd, "goto commit; /* DEBUG : never actually write. */\n\n"); + print_tabs(2, fd); + fprintf(fd, "*to_base = *to = *len = 0;\n"); + fprintf(fd, "\n"); + + /* Write event header */ + print_tabs(2, fd); + fprintf(fd, "ltt_write_event_header(trace, channel, buffer,\n"); + print_tabs(3, fd); + fprintf(fd, "ltt_facility_%s_%X, event_%s_%s,\n", fac->name, fac->checksum, + fac->name, event->name); + print_tabs(3, fd); + fprintf(fd, "reserve_size, before_hdr_pad, tsc);\n"); + print_tabs(2, fd); + fprintf(fd, "*to_base += before_hdr_pad + after_hdr_pad + header_size;\n"); + fprintf(fd, "\n"); + + /* write data. */ + + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(event->fields.array[i]); + type_descriptor_t *type = field->type; + + /* Set from */ + print_tabs(2, fd); + switch(type->type) { + case SEQUENCE: + case UNION: + case ARRAY: + case STRUCT: + case STRING: + fprintf(fd, "*from = (const char*)lttng_param_%s;\n", field->name); + break; + default: + fprintf(fd, "*from = (const char*)<tng_param_%s;\n", field->name); + break; + } + + + if(print_type_write(type, + fd, 2, basename, field->name, "lttng_param_", 0)) return 1; + fprintf(fd, "\n"); + + /* Don't forget to flush pending memcpy */ + print_tabs(2, fd); + fprintf(fd, "/* Flush pending memcpy */\n"); + print_tabs(2, fd); + fprintf(fd, "if (*len != 0) {\n"); + print_tabs(3, fd); + fprintf(fd, "memcpy(buffer+*to_base+*to, *from, *len);\n"); + print_tabs(3, fd); + fprintf(fd, "*to += *len;\n"); + //print_tabs(3, fd); + //fprintf(fd, "from += len;\n"); + print_tabs(3, fd); + fprintf(fd, "*len = 0;\n"); + print_tabs(2, fd); + fprintf(fd, "}\n"); + fprintf(fd, "\n"); + } + + + /* commit */ + // for DEBUG only. + //fprintf(fd, "commit:\n"); /* DEBUG! */ + print_tabs(2, fd); + fprintf(fd, "ltt_commit_slot(channel, &transport_data, buffer, slot_size);\n\n"); + + print_tabs(1, fd); + fprintf(fd, "}\n\n"); + + /* Release locks */ + print_tabs(1, fd); + fprintf(fd, "ltt_nesting[smp_processor_id()]--;\n"); + print_tabs(1, fd); + fprintf(fd, "preempt_enable();\n"); + + fprintf(fd, "}\n"); +#if 0 + fprintf(fd, "#endif //(!defined(CONFIG_LTT) || (!defined(CONFIG_LTT_FACILITY_%s) && !defined(CONFIG_LTT_FACILITY_%s_MODULE)))\n\n", + fac->capname, fac->capname); +#endif //0 + return 0; } +int print_event_logging_function_header_user_generic(char *basename, facility_t *fac, + event_t *event, FILE *fd, enum user_fct_types fct_type) +{ + char *attrib; -/***************************************************************************** - *Function name - * generateEnumEvent : output event enum to .h file - *Input Params - * fp : file to be written to - * facName : name of facility - *Output Params - * nbEvent : number of events in the facility - ****************************************************************************/ -void generateEnumEvent(FILE *fp, char *facName, int * nbEvent, unsigned long checksum) { - int pos = 0; + if(event->no_instrument_function && fct_type == USER_FCT_PROTO) { + attrib = "__attribute__((no_instrument_function)) "; + } else { + attrib = ""; + } + if(event->param_buffer) { + fprintf(fd, "static inline %sint trace_%s_param_buffer(\n", attrib, basename); + } else { + fprintf(fd, "static inline %sint trace_%s(\n",attrib, basename); + } + int has_argument = 0; + + if(event->param_buffer) { + if(has_argument) { + fprintf(fd, ","); + fprintf(fd, "\n"); + } + print_tabs(2, fd); + fprintf(fd, "char *buffer"); + has_argument = 1; + fprintf(fd, ","); + fprintf(fd, "\n"); + print_tabs(2, fd); + fprintf(fd, "size_t reserve_size"); + } else { + for(unsigned int j = 0; j < event->fields.position; j++) { + /* For each field, print the function argument */ + field_t *f = (field_t*)event->fields.array[j]; + type_descriptor_t *t = f->type; + if(has_argument) { + fprintf(fd, ","); + fprintf(fd, "\n"); + } + if(print_arg(t, fd, 2, basename, f->name)) return 1; + has_argument = 1; + } + } + if(!has_argument) { + print_tabs(2, fd); + fprintf(fd, "void"); + } + fprintf(fd,")"); + return 0; +} + + +/* print_event_logging_function_user_generic + * Print the logging function of an event for userspace tracing. This is the + * core of genevent */ +int print_event_logging_function_user_generic(char *basename, facility_t *fac, + event_t *event, FILE *fd) +{ + int has_type_fixed = 0; + + if(print_event_logging_function_header_user_generic(basename, fac, event, fd, USER_FCT_PROTO)) return 1; + fprintf(fd,";\n"); + fprintf(fd,"\n"); + fprintf(fd, "#ifndef LTT_TRACE_FAST\n"); + if(print_event_logging_function_header_user_generic(basename, fac, event, fd, USER_FCT_DECLARATION)) return 1; + fprintf(fd,"\n"); + fprintf(fd, + "#ifndef LTT_TRACE\n"); + fprintf(fd, "{\n"); + fprintf(fd, "}\n"); + fprintf(fd,"#else\n"); + fprintf(fd, "{\n"); + /* Print the function variables */ + print_tabs(1, fd); + fprintf(fd, "int ret = 0;\n"); + if(event->param_buffer) { + //FIX print_tabs(1, fd); + //fprintf(fd, "reserve_size = ltt_align(reserve_size, sizeof(void *));\n"); + print_tabs(1, fd); + fprintf(fd, "{\n"); + goto do_syscall; + } + print_tabs(1, fd); + fprintf(fd, "char *buffer = NULL;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t real_to_base = 0; /* The buffer is allocated on arch_size alignment */\n"); + print_tabs(1, fd); + fprintf(fd, "size_t *to_base = &real_to_base;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t real_to = 0;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t *to = &real_to;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t real_len = 0;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t *len = &real_len;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t reserve_size;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t slot_size;\n"); + print_tabs(1, fd); + + if(event->fields.position > 0) { + for(unsigned int i=0;ifields.position;i++){ + /* Search for at least one child with fixed size. It means + * we need local variables.*/ + field_t *field = (field_t*)(event->fields.array[i]); + type_descriptor_t *type = field->type; + has_type_fixed = has_type_local(type); + if(has_type_fixed) break; + } + + if(has_type_fixed) { + fprintf(fd, "size_t align;\n"); + print_tabs(1, fd); + } + + fprintf(fd, "const char *real_from;\n"); + print_tabs(1, fd); + fprintf(fd, "const char **from = &real_from;\n"); + print_tabs(1, fd); + } + + /* Calculate event variable len + event data alignment offset. + * Assume that the padding for alignment starts at a void* + * address. + * This excludes the header size and alignment. */ + + print_tabs(1, fd); + fprintf(fd, "/* For each field, calculate the field size. */\n"); + print_tabs(1, fd); + fprintf(fd, "/* size = *to_base + *to + *len */\n"); + print_tabs(1, fd); + fprintf(fd, "/* Assume that the padding for alignment starts at a\n"); + print_tabs(1, fd); + fprintf(fd, " * sizeof(void *) address. */\n"); + fprintf(fd, "\n"); + + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(event->fields.array[i]); + type_descriptor_t *type = field->type; + /* Set from */ + print_tabs(1, fd); + switch(type->type) { + case SEQUENCE: + case UNION: + case ARRAY: + case STRUCT: + case STRING: + fprintf(fd, "*from = (const char*)lttng_param_%s;\n", field->name); + break; + default: + fprintf(fd, "*from = (const char*)<tng_param_%s;\n", field->name); + break; + } + + if(print_type_write(type, + fd, 1, basename, field->name, "lttng_param_", 0)) return 1; + fprintf(fd, "\n"); + } + print_tabs(1, fd); + fprintf(fd, "reserve_size = *to_base + *to + *len;\n"); + + print_tabs(1, fd); + fprintf(fd, "{\n"); + print_tabs(2, fd); + fprintf(fd, "char stack_buffer[reserve_size];\n"); + print_tabs(2, fd); + fprintf(fd, "buffer = stack_buffer;\n"); + fprintf(fd, "\n"); + + + //print_tabs(2, fd); + // for DEBUG only + // fprintf(fd, "goto commit; /* DEBUG : never actually write. */\n\n"); + print_tabs(2, fd); + fprintf(fd, "*to_base = *to = *len = 0;\n"); + fprintf(fd, "\n"); + + /* write data. */ + + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(event->fields.array[i]); + type_descriptor_t *type = field->type; + + /* Set from */ + print_tabs(2, fd); + switch(type->type) { + case SEQUENCE: + case UNION: + case ARRAY: + case STRUCT: + case STRING: + fprintf(fd, "*from = (const char*)lttng_param_%s;\n", field->name); + break; + default: + fprintf(fd, "*from = (const char*)<tng_param_%s;\n", field->name); + break; + } + + + if(print_type_write(type, + fd, 2, basename, field->name, "lttng_param_", 0)) return 1; + fprintf(fd, "\n"); + + /* Don't forget to flush pending memcpy */ + print_tabs(2, fd); + fprintf(fd, "/* Flush pending memcpy */\n"); + print_tabs(2, fd); + fprintf(fd, "if (*len != 0) {\n"); + print_tabs(3, fd); + fprintf(fd, "memcpy(buffer+*to_base+*to, *from, *len);\n"); + print_tabs(3, fd); + fprintf(fd, "*to += *len;\n"); + //print_tabs(3, fd); + //fprintf(fd, "from += len;\n"); + print_tabs(3, fd); + fprintf(fd, "*len = 0;\n"); + print_tabs(2, fd); + fprintf(fd, "}\n"); + fprintf(fd, "\n"); + } - fprintf(fp,"#include \n\n"); +do_syscall: + print_tabs(2, fd); + fprintf(fd, "ret = ltt_trace_generic(ltt_facility_%s_%X, event_%s_%s, buffer, reserve_size, LTT_BLOCKING, %u);\n", fac->name, fac->checksum, fac->name, event->name, event->high_priority); - fprintf(fp,"/**** facility handle ****/\n\n"); - fprintf(fp,"extern trace_facility_t ltt_facility_%s_%X;\n\n\n",facName, checksum); + print_tabs(1, fd); + fprintf(fd, "}\n\n"); + + print_tabs(1, fd); + fprintf(fd, "return ret;\n\n"); - fprintf(fp,"/**** event type ****/\n\n"); - fprintf(fp,"enum %s_event {\n",facName); + fprintf(fd, "}\n"); + fprintf(fd, + "#endif //LTT_TRACE\n"); + fprintf(fd, "#endif //!LTT_TRACE_FAST\n\n"); - for(pos = 0; pos < fac->events.position;pos++) { - fprintf(fp,"\t%s", ((event *)(fac->events.array[pos]))->name); - if(pos != fac->events.position-1) fprintf(fp,",\n"); - } - fprintf(fp,"\n};\n\n\n"); + return 0; +} - // fprintf(fp,"/**** number of events in the facility ****/\n\n"); - // fprintf(fp,"int nbEvents_%s = %d;\n\n\n",facName, fac->events.position); - *nbEvent = fac->events.position; +/* print_event_logging_function_user_fast + * Print the logging function of an event for userspace tracing. This is the + * core of genevent */ +int print_event_logging_function_user_fast(char *basename, facility_t *fac, + event_t *event, FILE *fd) +{ + char *attrib; + + fprintf(fd, "#ifdef LTT_TRACE_FAST\n"); + + if(event->no_instrument_function) { + attrib = "__attribute__((no_instrument_function)) "; + } else { + attrib = ""; + } + fprintf(fd, "static inline %sint trace_%s(\n",attrib, basename); + + int has_argument = 0; + int has_type_fixed = 0; + + for(unsigned int j = 0; j < event->fields.position; j++) { + /* For each field, print the function argument */ + field_t *f = (field_t*)event->fields.array[j]; + type_descriptor_t *t = f->type; + if(has_argument) { + fprintf(fd, ","); + fprintf(fd, "\n"); + } + if(print_arg(t, fd, 2, basename, f->name)) return 1; + has_argument = 1; + } + if(!has_argument) { + print_tabs(2, fd); + fprintf(fd, "void"); + } + fprintf(fd,")\n"); + fprintf(fd, + "#ifndef LTT_TRACE\n"); + fprintf(fd, "{\n"); + fprintf(fd, "}\n"); + fprintf(fd,"#else\n"); + fprintf(fd, "{\n"); + /* Print the function variables */ + print_tabs(1, fd); + fprintf(fd, "unsigned int index;\n"); + print_tabs(1, fd); + fprintf(fd, "struct ltt_trace_info *trace = thread_trace_info;\n"); + print_tabs(1, fd); + fprintf(fd, "struct ltt_buf *ltt_buf;\n"); + print_tabs(1, fd); + fprintf(fd, "char *buffer = NULL;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t real_to_base = 0; /* The buffer is allocated on arch_size alignment */\n"); + print_tabs(1, fd); + fprintf(fd, "size_t *to_base = &real_to_base;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t real_to = 0;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t *to = &real_to;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t real_len = 0;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t *len = &real_len;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t reserve_size;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t slot_size;\n"); + print_tabs(1, fd); + + if(event->fields.position > 0) { + for(unsigned int i=0;ifields.position;i++){ + /* Search for at least one child with fixed size. It means + * we need local variables.*/ + field_t *field = (field_t*)(event->fields.array[i]); + type_descriptor_t *type = field->type; + has_type_fixed = has_type_local(type); + if(has_type_fixed) break; + } + + if(has_type_fixed) { + fprintf(fd, "size_t align;\n"); + print_tabs(1, fd); + } + + fprintf(fd, "const char *real_from;\n"); + print_tabs(1, fd); + fprintf(fd, "const char **from = &real_from;\n"); + print_tabs(1, fd); + } + fprintf(fd, "uint64_t tsc;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t before_hdr_pad, after_hdr_pad, header_size;\n"); + fprintf(fd, "\n"); + + print_tabs(1, fd); + fprintf(fd, "if (!trace) {\n"); + print_tabs(2, fd); + fprintf(fd, "ltt_thread_init();\n"); + print_tabs(2, fd); + fprintf(fd, "trace = thread_trace_info;\n"); + print_tabs(1, fd); + fprintf(fd, "}\n\n"); + fprintf(fd, "\n"); + + /* Calculate event variable len + event data alignment offset. + * Assume that the padding for alignment starts at a void* + * address. + * This excludes the header size and alignment. */ + + print_tabs(1, fd); + fprintf(fd, "/* For each field, calculate the field size. */\n"); + print_tabs(1, fd); + fprintf(fd, "/* size = *to_base + *to + *len */\n"); + print_tabs(1, fd); + fprintf(fd, "/* Assume that the padding for alignment starts at a\n"); + print_tabs(1, fd); + fprintf(fd, " * sizeof(void *) address. */\n"); + fprintf(fd, "\n"); + + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(event->fields.array[i]); + type_descriptor_t *type = field->type; + /* Set from */ + print_tabs(1, fd); + switch(type->type) { + case SEQUENCE: + case UNION: + case ARRAY: + case STRUCT: + case STRING: + fprintf(fd, "*from = (const char*)lttng_param_%s;\n", field->name); + break; + default: + fprintf(fd, "*from = (const char*)<tng_param_%s;\n", field->name); + break; + } + + if(print_type_write(type, + fd, 1, basename, field->name, "lttng_param_", 0)) return 1; + fprintf(fd, "\n"); + } + print_tabs(1, fd); + fprintf(fd, "reserve_size = *to_base + *to + *len;\n"); + + print_tabs(1, fd); + fprintf(fd, "trace->nesting++;\n"); + + /* Get facility index */ + + print_tabs(1, fd); + fprintf(fd, + "index = ltt_get_index_from_facility(ltt_facility_%s_%X,\n"\ + "\t\t\t\t\t\tevent_%s_%s);\n", + fac->name, fac->checksum, fac->name, event->name); + fprintf(fd,"\n"); + + + print_tabs(1, fd); + fprintf(fd, "{\n"); + + if(event->per_trace) { + print_tabs(2, fd); + fprintf(fd, "if (dest_trace != trace) continue;\n\n"); + } + + print_tabs(2, fd); + fprintf(fd, "ltt_buf = ltt_get_channel_from_index(trace, index);\n"); + print_tabs(2, fd); + + + /* Relay reserve */ + /* If error, increment event lost counter (done by ltt_reserve_slot) and + * return */ + print_tabs(2, fd); + fprintf(fd, "slot_size = 0;\n"); + print_tabs(2, fd); + fprintf(fd, "buffer = ltt_reserve_slot(trace, ltt_buf,\n"); + print_tabs(3, fd); + fprintf(fd, "reserve_size, &slot_size, &tsc,\n"); + print_tabs(3, fd); + fprintf(fd, "&before_hdr_pad, &after_hdr_pad, &header_size);\n"); + /* If error, return */ + print_tabs(2, fd); + fprintf(fd, "if (!buffer)\n"); + print_tabs(3, fd); + fprintf(fd, "goto end; /* buffer full */\n\n"); + //print_tabs(2, fd); + // for DEBUG only + // fprintf(fd, "goto commit; /* DEBUG : never actually write. */\n\n"); + print_tabs(2, fd); + fprintf(fd, "*to_base = *to = *len = 0;\n"); + fprintf(fd, "\n"); + + /* Write event header */ + print_tabs(2, fd); + fprintf(fd, "ltt_write_event_header(trace, ltt_buf, buffer,\n"); + print_tabs(3, fd); + fprintf(fd, "ltt_facility_%s_%X, event_%s_%s,\n", fac->name, fac->checksum, + fac->name, event->name); + print_tabs(3, fd); + fprintf(fd, "reserve_size, before_hdr_pad, tsc);\n"); + print_tabs(2, fd); + fprintf(fd, "*to_base += before_hdr_pad + after_hdr_pad + header_size;\n"); + fprintf(fd, "\n"); + + /* write data. */ + + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(event->fields.array[i]); + type_descriptor_t *type = field->type; + + /* Set from */ + print_tabs(2, fd); + switch(type->type) { + case SEQUENCE: + case UNION: + case ARRAY: + case STRUCT: + case STRING: + fprintf(fd, "*from = (const char*)lttng_param_%s;\n", field->name); + break; + default: + fprintf(fd, "*from = (const char*)<tng_param_%s;\n", field->name); + break; + } + + + if(print_type_write(type, + fd, 2, basename, field->name, "lttng_param_", 0)) return 1; + fprintf(fd, "\n"); + + /* Don't forget to flush pending memcpy */ + print_tabs(2, fd); + fprintf(fd, "/* Flush pending memcpy */\n"); + print_tabs(2, fd); + fprintf(fd, "if (*len != 0) {\n"); + print_tabs(3, fd); + fprintf(fd, "memcpy(buffer+*to_base+*to, *from, *len);\n"); + print_tabs(3, fd); + fprintf(fd, "*to += *len;\n"); + //print_tabs(3, fd); + //fprintf(fd, "from += len;\n"); + print_tabs(3, fd); + fprintf(fd, "*len = 0;\n"); + print_tabs(2, fd); + fprintf(fd, "}\n"); + fprintf(fd, "\n"); + } + + + /* commit */ + // for DEBUG only. + //fprintf(fd, "commit:\n"); /* DEBUG! */ + print_tabs(2, fd); + fprintf(fd, "ltt_commit_slot(ltt_buf, buffer, slot_size);\n\n"); + + fprintf(fd, "}\n\n"); + + fprintf(fd, "end:\n"); + /* Release locks */ + print_tabs(1, fd); + fprintf(fd, "trace->nesting--;\n"); + + + fprintf(fd, "}\n"); + fprintf(fd, + "#endif //LTT_TRACE\n"); + fprintf(fd, "#endif //LTT_TRACE_FAST\n"); + + return 0; } -/***************************************************************************** - *Function name - * printStruct : Generic struct printing function - *Input Params - * fp : file to be written to - * len : number of fields - * array : array of field info - * name : basic struct name - * facName : name of facility - * whichTypeFirst : struct or array/sequence first - * hasStrSeq : string or sequence present? - * structCount : struct postfix - ****************************************************************************/ -static void -printStruct(FILE * fp, int len, void ** array, char * name, char * facName, - int * whichTypeFirst, int * hasStrSeq, int * structCount) + + + +/* ltt-facility-name.h : main logging header. + * log_header */ + +void print_log_header_head(facility_t *fac, FILE *fd) { - int flag = 0; - int pos; - field * fld; - type_descriptor * td; - - for (pos = 0; pos < len; pos++) { - fld = (field *)array[pos]; - td = fld->type; - if( td->type != STRING && td->type != SEQUENCE && - td->type != ARRAY) { - if (*whichTypeFirst == 0) { - *whichTypeFirst = 1; //struct first - } - if (flag == 0) { - flag = 1; - - fprintf(fp,"struct %s_%s",name, facName); - if (structCount) { - fprintf(fp, "_%d {\n",++*structCount); - } else { - fprintf(fp, " {\n"); - } - } - fprintf(fp, "\t%s %s; /* %s */\n", - getTypeStr(td),fld->name,fld->description ); - } else { - if (*whichTypeFirst == 0) { - //string or sequence or array first - *whichTypeFirst = 2; - } - (*hasStrSeq)++; - if(flag) { - fprintf(fp,"} __attribute__ ((packed));\n\n"); - } - flag = 0; - } - } + fprintf(fd, "#ifndef _LTT_FACILITY_%s_H_\n", fac->capname); + fprintf(fd, "#define _LTT_FACILITY_%s_H_\n\n", fac->capname); + fprintf(fd, "#include \n"); + if(!fac->arch) + fprintf(fd, "#include \n", fac->name); + else + fprintf(fd, "#include \n", + fac->name, + fac->arch); + fprintf(fd, "#include \n"); + fprintf(fd, "\n"); +} - if(flag) { - fprintf(fp,"} __attribute__ ((packed));\n\n"); - } +/* ltt-facility-name.h : main logging header. + * log_header */ + +void print_log_header_head_user(facility_t *fac, FILE *fd) +{ + fprintf(fd, "#ifndef _LTT_FACILITY_%s_H_\n", fac->capname); + fprintf(fd, "#define _LTT_FACILITY_%s_H_\n\n", fac->capname); + fprintf(fd, "#include \n"); + if(!fac->arch) + fprintf(fd, "#include \n", fac->name); + else + fprintf(fd, "#include \n", + fac->name, + fac->arch); + fprintf(fd, "#include \n"); + fprintf(fd, "\n"); + fprintf(fd, "#ifdef __cplusplus\n"); + fprintf(fd, "extern \"C\" {\n"); + fprintf(fd, "#endif\n"); + fprintf(fd, "\n"); } -/***************************************************************************** - *Function name - * generateHfile : Create the typedefs - *Input Params - * fp : file to be written to - ****************************************************************************/ -void -generateTypeDefs(FILE * fp) +int print_log_header_types(facility_t *fac, FILE *fd) +{ + sequence_t *types = &fac->named_types.values; + fprintf(fd, "/* Named types */\n"); + fprintf(fd, "\n"); + + for(unsigned int i = 0; i < types->position; i++) { + /* For each named type, print the definition */ + if(print_type_declaration(types->array[i], fd, + 0, "", "")) return 1; + /* Print also the align function */ + if(print_type_alignment_fct(types->array[i], fd, + 0, "", "")) return 1; + /* Print also the write function */ + if(print_type_write_fct(types->array[i], fd, + 0, "", "")) return 1; + } + return 0; +} + +int print_log_header_events(facility_t *fac, FILE *fd) { - int pos, tmp = 1; + sequence_t *events = &fac->events; + char basename[PATH_MAX]; + unsigned int facname_len; + + strncpy(basename, fac->name, PATH_MAX); + facname_len = strlen(basename); + strncat(basename, "_", PATH_MAX-facname_len); + facname_len = strlen(basename); + + for(unsigned int i = 0; i < events->position; i++) { + event_t *event = (event_t*)events->array[i]; + strncpy(&basename[facname_len], event->name, PATH_MAX-facname_len); + + /* For each event, print structure, and then logging function */ + fprintf(fd, "/* Event %s structures */\n", + event->name); + for(unsigned int j = 0; j < event->fields.position; j++) { + /* For each unnamed type, print the definition */ + field_t *f = (field_t*)event->fields.array[j]; + type_descriptor_t *t = f->type; + if(t->type_name == NULL) { + if((print_type_declaration(t, fd, 0, basename, f->name))) return 1; + /* Print also the align function */ + if((print_type_alignment_fct(t, fd, 0, basename, f->name))) return 1; + /* Print also the write function */ + if((print_type_write_fct(t, fd, 0, basename, f->name))) return 1; + } + } + + fprintf(fd, "\n"); + + fprintf(fd, "/* Event %s logging function */\n", + event->name); + + if(!fac->user) { + if(print_event_logging_function(basename, fac, event, fd)) return 1; + } else { + if(print_event_logging_function_user_generic(basename, fac, event, fd)) + return 1; + if(print_event_logging_function_user_fast(basename, fac, event, fd)) + return 1; + } + + fprintf(fd, "\n"); + } + + return 0; +} - fprintf(fp, "/**** Basic Type Definitions ****/\n\n"); - for (pos = 0; pos < fac->named_types.values.position; pos++) { - type_descriptor * type = - (type_descriptor*)fac->named_types.values.array[pos]; - printStruct(fp, type->fields.position, type->fields.array, - "", type->type_name, &tmp, &tmp, NULL); - fprintf(fp, "typedef struct _%s %s;\n\n", - type->type_name, type->type_name); - } +void print_log_header_tail(facility_t *fac, FILE *fd) +{ + fprintf(fd, "#endif //_LTT_FACILITY_%s_H_\n",fac->capname); } +void print_log_header_tail_user(facility_t *fac, FILE *fd) +{ + fprintf(fd, "#ifdef __cplusplus\n"); + fprintf(fd, "} /* end of extern \"C\" */\n"); + fprintf(fd, "#endif\n"); + fprintf(fd, "\n"); + fprintf(fd, "#endif //_LTT_FACILITY_%s_H_\n",fac->capname); +} + +int print_log_header(facility_t *fac) +{ + char filename[PATH_MAX]; + unsigned int filename_size = 0; + FILE *fd; + dprintf("%s\n", fac->name); + + strcpy(filename, "ltt-facility-"); + filename_size = strlen(filename); + + strncat(filename, fac->name, PATH_MAX - filename_size); + filename_size = strlen(filename); + + if(fac->arch) { + strncat(filename, "_", PATH_MAX - filename_size); + filename_size = strlen(filename); + + strncat(filename, fac->arch, PATH_MAX - filename_size); + filename_size = strlen(filename); + } -/***************************************************************************** - *Function name - * generateEnumDefinition: generate enum definition if it exists - *Input Params - * fp : file to be written to - * fHead : enum type - ****************************************************************************/ -void generateEnumDefinition(FILE * fp, type_descriptor * type){ - int pos; + strncat(filename, ".h", PATH_MAX - filename_size); + filename_size = strlen(filename); + - fprintf(fp,"enum {\n"); - for(pos = 0; pos < type->labels.position; pos++){ - fprintf(fp,"\t%s", type->labels.array[pos]); - if (pos != type->labels.position - 1) fprintf(fp,",\n"); - } - fprintf(fp,"\n};\n\n\n"); + fd = fopen(filename, "w"); + if(fd == NULL) { + printf("Error opening file %s for writing : %s\n", + filename, strerror(errno)); + return errno; + } + + /* Print file head */ + if(!fac->user) + print_log_header_head(fac, fd); + else + print_log_header_head_user(fac, fd); + + /* print named types in declaration order */ + if(print_log_header_types(fac, fd)) return 1; + + /* Print events */ + if(print_log_header_events(fac, fd)) return 1; + + /* Print file tail */ + if(!fac->user) + print_log_header_tail(fac, fd); + else + print_log_header_tail_user(fac, fd); + + + + fclose(fd); + + return 0; } -/***************************************************************************** - *Function name - * generateStrucTFunc: output structure and function to .h file - *Input Params - * fp : file to be written to - * facName : name of facility - ****************************************************************************/ -void generateStructFunc(FILE * fp, char * facName, unsigned long checksum){ - event * ev; - field * fld; - type_descriptor * td; - int pos, pos1; - int hasStrSeq, flag, structCount, seqCount,strCount, whichTypeFirst=0; - - for(pos = 0; pos < fac->events.position; pos++){ - ev = (event *) fac->events.array[pos]; - //yxx if(ev->nested)continue; - fprintf(fp,"/**** structure and trace function for event: %s ****/\n\n",ev->name); - if(ev->type == 0){ // event without type - fprintf(fp,"static inline void trace_%s_%s(void){\n",facName,ev->name); - fprintf(fp,"\tltt_log_event(ltt_facility_%s_%X, %s, 0, NULL);\n",facName,checksum,ev->name); - fprintf(fp,"};\n\n\n"); - continue; - } - - //if fields contain enum, print out enum definition - for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){ - fld = (field *)ev->type->fields.array[pos1]; - if(fld->type->type == ENUM) generateEnumDefinition(fp, fld->type); - } - - //default: no string, array or sequence in the event - hasStrSeq = 0; - whichTypeFirst = 0; - structCount = 0; - - //structure for kernel - printStruct(fp, ev->type->fields.position, ev->type->fields.array, - ev->name, facName, &whichTypeFirst, &hasStrSeq, &structCount); - - //trace function : function name and parameters - seqCount = 0; - strCount = 0; - fprintf(fp,"static inline void trace_%s_%s(",facName,ev->name); - for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){ - fld = (field *)ev->type->fields.array[pos1]; - td = fld->type; - if(td->type == ARRAY ){ - fprintf(fp,"%s * %s",getTypeStr(td), fld->name); - }else if(td->type == STRING){ - fprintf(fp,"short int strLength_%d, %s * %s",++strCount, getTypeStr(td), fld->name); - }else if(td->type == SEQUENCE){ - fprintf(fp,"%s seqLength_%d, %s * %s",uintOutputTypes[td->size], ++seqCount,getTypeStr(td), fld->name); - }else fprintf(fp,"%s %s",getTypeStr(td), fld->name); - if(pos1 != ev->type->fields.position -1)fprintf(fp,", "); - } - fprintf(fp,"){\n"); - - //length of buffer : length of all structures - fprintf(fp,"\tint bufLength = "); - for(pos1=0;pos1name, facName,pos1+1); - if(pos1 != structCount-1) fprintf(fp," + "); - } - - //length of buffer : length of all arrays, sequences and strings - seqCount = 0; - strCount = 0; - flag = 0; - for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){ - fld = (field *)ev->type->fields.array[pos1]; - td = fld->type; - if(td->type == SEQUENCE || td->type==STRING ||td->type==ARRAY){ - if(structCount || flag > 0) fprintf(fp," + "); - if(td->type == SEQUENCE) fprintf(fp,"sizeof(%s) + sizeof(%s) * seqLength_%d",uintOutputTypes[td->size], getTypeStr(td), ++seqCount); - else if(td->type==STRING) fprintf(fp,"strLength_%d + 1", ++strCount); - else if(td->type==ARRAY) fprintf(fp,"sizeof(%s) * %d", getTypeStr(td),td->size); - if(structCount == 0) flag = 1; - } - } - fprintf(fp,";\n"); - - //allocate buffer - fprintf(fp,"\tchar buff[bufLength];\n"); - - //declare a char pointer if needed - if(structCount + hasStrSeq > 1) fprintf(fp,"\tchar * ptr = buff;\n"); - - //allocate memory for new struct and initialize it - if(whichTypeFirst == 1){ //struct first - for(pos1=0;pos1name, facName,ev->name, facName); - else fprintf(fp,"\tstruct %s_%s_%d __%d;\n",ev->name, facName,pos1+1,pos1+1); - } - }else if(whichTypeFirst == 2){ - for(pos1=0;pos1name, facName,pos1+1,pos1+1); - } - fprintf(fp,"\n"); - - if(structCount) fprintf(fp,"\t//initialize structs\n"); - flag = 0; - structCount = 0; - for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){ - fld = (field *)ev->type->fields.array[pos1]; - td = fld->type; - if(td->type != ARRAY && td->type != SEQUENCE && td->type != STRING){ - if(flag == 0){ - flag = 1; - structCount++; - if(structCount > 1) fprintf(fp,"\n"); - } - if(structCount == 1 && whichTypeFirst == 1) fprintf(fp, "\t__1->%s = %s;\n",fld->name,fld->name ); - else fprintf(fp, "\t__%d.%s = %s;\n",structCount ,fld->name,fld->name); - }else flag = 0; - } - if(structCount) fprintf(fp,"\n"); - - //set ptr to the end of first struct if needed; - if(whichTypeFirst == 1 && structCount + hasStrSeq > 1){ - fprintf(fp,"\n\t//set ptr to the end of the first struct\n"); - fprintf(fp,"\tptr += sizeof(struct %s_%s_1);\n\n",ev->name, facName); - } - - //copy struct, sequence and string to buffer - seqCount = 0; - strCount = 0; - flag = 0; - structCount = 0; - for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){ - fld = (field *)ev->type->fields.array[pos1]; - td = fld->type; - if(td->type != STRING && td->type != SEQUENCE && td->type != ARRAY){ - if(flag == 0) structCount++; - flag++; - if((structCount > 1 || whichTypeFirst == 2) && flag == 1){ - fprintf(fp,"\t//copy struct to buffer\n"); - fprintf(fp,"\tmemcpy(ptr, &__%d, sizeof(struct %s_%s_%d));\n",structCount, ev->name, facName,structCount); - fprintf(fp,"\tptr += sizeof(struct %s_%s_%d);\n\n",ev->name, facName,structCount); - } - }else if(td->type == SEQUENCE){ - flag = 0; - fprintf(fp,"\t//copy sequence length and sequence to buffer\n"); - fprintf(fp,"\t*ptr = seqLength_%d;\n",++seqCount); - fprintf(fp,"\tptr += sizeof(%s);\n",uintOutputTypes[td->size]); - fprintf(fp,"\tmemcpy(ptr, %s, sizeof(%s) * seqLength_%d);\n",fld->name, getTypeStr(td), seqCount); - fprintf(fp,"\tptr += sizeof(%s) * seqLength_%d;\n\n",getTypeStr(td), seqCount ); - }else if(td->type==STRING){ - flag = 0; - fprintf(fp,"\t//copy string to buffer\n"); - fprintf(fp,"\tif(strLength_%d > 0){\n",++strCount); - fprintf(fp,"\t\tmemcpy(ptr, %s, strLength_%d + 1);\n", fld->name, strCount); - fprintf(fp,"\t\tptr += strLength_%d + 1;\n",strCount); - fprintf(fp,"\t}else{\n"); - fprintf(fp,"\t\t*ptr = '\\0';\n"); - fprintf(fp,"\t\tptr += 1;\n"); - fprintf(fp,"\t}\n\n"); - }else if(td->type==ARRAY){ - flag = 0; - fprintf(fp,"\t//copy array to buffer\n"); - fprintf(fp,"\tmemcpy(ptr, %s, sizeof(%s) * %d);\n", fld->name, getTypeStr(td), td->size); - fprintf(fp,"\tptr += sizeof(%s) * %d;\n\n",getTypeStr(td), td->size); - } - } - if(structCount + seqCount > 1) fprintf(fp,"\n"); - - //call trace function - fprintf(fp,"\n\t//call trace function\n"); - fprintf(fp,"\tltt_log_event(ltt_facility_%s_%X, %s, bufLength, buff);\n",facName,checksum,ev->name); - fprintf(fp,"};\n\n\n"); - } +/* ltt-facility-id-name.h : facility id. + * log_id_header */ +int print_id_header(facility_t *fac) +{ + char filename[PATH_MAX]; + unsigned int filename_size = 0; + FILE *fd; + char basename[PATH_MAX]; + char basename_len = 0; + + dprintf("%s\n", fac->name); + + strcpy(filename, "ltt-facility-id-"); + filename_size = strlen(filename); + + strncat(filename, fac->name, PATH_MAX - filename_size); + filename_size = strlen(filename); + + if(fac->arch) { + strncat(filename, "_", PATH_MAX - filename_size); + filename_size = strlen(filename); + + strncat(filename, fac->arch, PATH_MAX - filename_size); + filename_size = strlen(filename); + } + + strncat(filename, ".h", PATH_MAX - filename_size); + filename_size = strlen(filename); + + + fd = fopen(filename, "w"); + if(fd == NULL) { + printf("Error opening file %s for writing : %s\n", + filename, strerror(errno)); + return errno; + } + + if(!fac->user) { + fprintf(fd, "#ifndef _LTT_FACILITY_ID_%s_H_\n",fac->capname); + fprintf(fd, "#define _LTT_FACILITY_ID_%s_H_\n\n",fac->capname); + fprintf(fd, "#ifdef CONFIG_LTT\n"); + + fprintf(fd,"#include \n\n"); + + fprintf(fd,"/**** facility handle ****/\n\n"); + fprintf(fd,"extern ltt_facility_t ltt_facility_%s_%X;\n", + fac->name, fac->checksum); + fprintf(fd,"extern ltt_facility_t ltt_facility_%s;\n\n\n",fac->name); + + strncpy(basename, fac->name, PATH_MAX); + basename_len = strlen(basename); + strncat(basename, "_", PATH_MAX - basename_len); + basename_len++; + + fprintf(fd,"/**** event index ****/\n\n"); + fprintf(fd,"enum %s_event {\n",fac->name); + + for(unsigned int i = 0; i < fac->events.position; i++) { + event_t *event = (event_t*)fac->events.array[i]; + strncpy(basename+basename_len, event->name, PATH_MAX-basename_len); + print_tabs(1, fd); + fprintf(fd, "event_%s,\n", basename); + } + print_tabs(1, fd); + fprintf(fd, "facility_%s_num_events\n", fac->name); + fprintf(fd, "};\n"); + fprintf(fd, "\n"); + + + fprintf(fd, "#endif //CONFIG_LTT\n"); + fprintf(fd, "#endif //_LTT_FACILITY_ID_%s_H_\n",fac->capname); + } else { + fprintf(fd, "#ifndef _LTT_FACILITY_ID_%s_H_\n",fac->capname); + fprintf(fd, "#define _LTT_FACILITY_ID_%s_H_\n\n",fac->capname); + fprintf(fd, "#ifdef LTT_TRACE\n"); + + fprintf(fd,"#include \n\n"); + + fprintf(fd,"/**** facility handle ****/\n\n"); + fprintf(fd,"extern ltt_facility_t ltt_facility_%s_%X;\n", + fac->name, fac->checksum); + fprintf(fd,"extern ltt_facility_t ltt_facility_%s;\n\n\n",fac->name); + + strncpy(basename, fac->name, PATH_MAX); + basename_len = strlen(basename); + strncat(basename, "_", PATH_MAX - basename_len); + basename_len++; + + fprintf(fd,"/**** event index ****/\n\n"); + fprintf(fd,"enum %s_event {\n",fac->name); + + for(unsigned int i = 0; i < fac->events.position; i++) { + event_t *event = (event_t*)fac->events.array[i]; + strncpy(basename+basename_len, event->name, PATH_MAX-basename_len); + print_tabs(1, fd); + fprintf(fd, "event_%s,\n", basename); + } + print_tabs(1, fd); + fprintf(fd, "facility_%s_num_events\n", fac->name); + fprintf(fd, "};\n"); + fprintf(fd, "\n"); + + + fprintf(fd, "#endif //LTT_TRACE\n"); + fprintf(fd, "#endif //_LTT_FACILITY_ID_%s_H_\n",fac->capname); + } + + + fclose(fd); + + return 0; } -/***************************************************************************** - *Function name - * getTypeStr : generate type string - *Input Params - * td : a type descriptor - *Return Values - * char * : type string - ****************************************************************************/ -char * getTypeStr(type_descriptor * td){ - type_descriptor * t ; - - switch(td->type){ - case INT: - return intOutputTypes[td->size]; - case UINT: - return uintOutputTypes[td->size]; - case POINTER: - return "void *"; - case LONG: - return "long"; - case ULONG: - return "unsigned long"; - case SIZE_T: - return "size_t"; - case SSIZE_T: - return "ssize_t"; - case OFF_T: - return "off_t"; - case FLOAT: - return floatOutputTypes[td->size]; - case STRING: - return "char"; - case ENUM: - return uintOutputTypes[td->size]; - case ARRAY: - case SEQUENCE: - t = td->nested_type; - switch(t->type){ - case INT: - return intOutputTypes[t->size]; - case UINT: - return uintOutputTypes[t->size]; - case POINTER: - return "void *"; - case LONG: - return "long"; - case ULONG: - return "unsigned long"; - case SIZE_T: - return "size_t"; - case SSIZE_T: - return "ssize_t"; - case OFF_T: - return "off_t"; - case FLOAT: - return floatOutputTypes[t->size]; - case STRING: - return "char"; - case ENUM: - return uintOutputTypes[t->size]; - default : - error_callback(NULL,"Nested struct is not supportted"); - break; - } - break; - case STRUCT: //for now we do not support nested struct - error_callback(NULL,"Nested struct is not supportted"); - break; - default: - error_callback(NULL,"No type information"); - break; - } - return NULL; + +/* ltt-facility-loader-name.h : facility specific loader info. + * loader_header */ +int print_loader_header(facility_t *fac) +{ + char filename[PATH_MAX]; + unsigned int filename_size = 0; + FILE *fd; + dprintf("%s\n", fac->name); + + strcpy(filename, "ltt-facility-loader-"); + filename_size = strlen(filename); + + strncat(filename, fac->name, PATH_MAX - filename_size); + filename_size = strlen(filename); + + if(fac->arch) { + strncat(filename, "_", PATH_MAX - filename_size); + filename_size = strlen(filename); + + strncat(filename, fac->arch, PATH_MAX - filename_size); + filename_size = strlen(filename); + } + + strncat(filename, ".h", PATH_MAX - filename_size); + filename_size = strlen(filename); + + + fd = fopen(filename, "w"); + if(fd == NULL) { + printf("Error opening file %s for writing : %s\n", + filename, strerror(errno)); + return errno; + } + + fprintf(fd, "#ifndef _LTT_FACILITY_LOADER_%s_H_\n", fac->capname); + fprintf(fd, "#define _LTT_FACILITY_LOADER_%s_H_\n\n", fac->capname); + fprintf(fd, "#ifdef CONFIG_LTT\n\n"); + fprintf(fd,"#include \n"); + if(!fac->arch) + fprintf(fd,"#include \n\n", + fac->name); + else + fprintf(fd,"#include \n\n", + fac->name, + fac->arch); + fprintf(fd,"ltt_facility_t\tltt_facility_%s;\n", fac->name); + fprintf(fd,"ltt_facility_t\tltt_facility_%s_%X;\n\n", + fac->name, fac->checksum); + + fprintf(fd,"#define LTT_FACILITY_SYMBOL\t\tltt_facility_%s\n", + fac->name); + fprintf(fd,"#define LTT_FACILITY_CHECKSUM_SYMBOL\tltt_facility_%s_%X\n", + fac->name, fac->checksum); + fprintf(fd,"#define LTT_FACILITY_CHECKSUM\t\t0x%X\n", fac->checksum); + fprintf(fd,"#define LTT_FACILITY_NAME\t\t\"%s\"\n", fac->name); + fprintf(fd,"#define LTT_FACILITY_NUM_EVENTS\tfacility_%s_num_events\n\n", + fac->name); + fprintf(fd, "#endif //CONFIG_LTT\n\n"); + fprintf(fd, "#endif //_LTT_FACILITY_LOADER_%s_H_\n", fac->capname); + + fclose(fd); + + return 0; } +int print_loader_header_user(facility_t *fac) +{ + char filename[PATH_MAX]; + unsigned int filename_size = 0; + FILE *fd; + dprintf("%s\n", fac->name); + + strcpy(filename, "ltt-facility-loader-"); + filename_size = strlen(filename); + + strncat(filename, fac->name, PATH_MAX - filename_size); + filename_size = strlen(filename); + + if(fac->arch) { + strncat(filename, "_", PATH_MAX - filename_size); + filename_size = strlen(filename); + + strncat(filename, fac->arch, PATH_MAX - filename_size); + filename_size = strlen(filename); + } + + strncat(filename, ".h", PATH_MAX - filename_size); + filename_size = strlen(filename); + + + fd = fopen(filename, "w"); + if(fd == NULL) { + printf("Error opening file %s for writing : %s\n", + filename, strerror(errno)); + return errno; + } + + fprintf(fd, "#ifndef _LTT_FACILITY_LOADER_%s_H_\n", fac->capname); + fprintf(fd, "#define _LTT_FACILITY_LOADER_%s_H_\n\n", fac->capname); + fprintf(fd,"#include \n"); + if(!fac->arch) + fprintf(fd,"#include \n\n", + fac->name); + else + fprintf(fd,"#include \n\n", + fac->name, + fac->arch); + fprintf(fd,"ltt_facility_t\tltt_facility_%s;\n", fac->name); + fprintf(fd,"ltt_facility_t\tltt_facility_%s_%X;\n\n", + fac->name, fac->checksum); + + fprintf(fd,"#define LTT_FACILITY_SYMBOL\t\t\t\t\t\t\tltt_facility_%s\n", + fac->name); + fprintf(fd,"#define LTT_FACILITY_CHECKSUM_SYMBOL\t\tltt_facility_%s_%X\n", + fac->name, fac->checksum); + fprintf(fd,"#define LTT_FACILITY_CHECKSUM\t\t\t\t\t\t0x%X\n", fac->checksum); + fprintf(fd,"#define LTT_FACILITY_NAME\t\t\t\t\t\t\t\t\"%s\"\n", fac->name); + fprintf(fd,"#define LTT_FACILITY_NUM_EVENTS\t\t\t\t\tfacility_%s_num_events\n\n", + fac->name); + fprintf(fd, "#endif //_LTT_FACILITY_LOADER_%s_H_\n", fac->capname); + + fclose(fd); + + return 0; +} + + + +/* ltt-facility-loader-name.c : generic facility loader + * loader_c */ +int print_loader_c(facility_t *fac) +{ + char filename[PATH_MAX]; + unsigned int filename_size = 0; + FILE *fd; + dprintf("%s\n", fac->name); + + strcpy(filename, "ltt-facility-loader-"); + filename_size = strlen(filename); + + strncat(filename, fac->name, PATH_MAX - filename_size); + filename_size = strlen(filename); + + if(fac->arch) { + strncat(filename, "_", PATH_MAX - filename_size); + filename_size = strlen(filename); + + strncat(filename, fac->arch, PATH_MAX - filename_size); + filename_size = strlen(filename); + } + + strncat(filename, ".c", PATH_MAX - filename_size); + filename_size = strlen(filename); + + + fd = fopen(filename, "w"); + if(fd == NULL) { + printf("Error opening file %s for writing : %s\n", + filename, strerror(errno)); + return errno; + } + + fprintf(fd, "/*\n"); + if(!fac->arch) + fprintf(fd, " * ltt-facility-loader-%s.c\n", fac->name); + else + fprintf(fd, " * ltt-facility-loader-%s_%s.c\n", fac->name, fac->arch); + fprintf(fd, " *\n"); + fprintf(fd, " * (C) Copyright 2005 - \n"); + fprintf(fd, " * Mathieu Desnoyers (mathieu.desnoyers@polymtl.ca)\n"); + fprintf(fd, " *\n"); + fprintf(fd, " * Contains the LTT facility loader.\n"); + fprintf(fd, " *\n"); + fprintf(fd, " */\n"); + fprintf(fd, "\n"); + fprintf(fd, "\n"); + fprintf(fd, "#include \n"); + fprintf(fd, "#include \n"); + fprintf(fd, "#include \n"); + if(!fac->arch) + fprintf(fd, "#include \"ltt-facility-loader-%s.h\"\n", fac->name); + else + fprintf(fd, "#include \"ltt-facility-loader-%s_%s.h\"\n", + fac->name, fac->arch); + fprintf(fd, "\n"); + fprintf(fd, "\n"); + fprintf(fd, "#ifdef CONFIG_LTT\n"); + fprintf(fd, "\n"); + fprintf(fd, "EXPORT_SYMBOL(LTT_FACILITY_SYMBOL);\n"); + fprintf(fd, "EXPORT_SYMBOL(LTT_FACILITY_CHECKSUM_SYMBOL);\n"); + fprintf(fd, "\n"); + fprintf(fd, "static const char ltt_facility_name[] = LTT_FACILITY_NAME;\n"); + fprintf(fd, "\n"); + fprintf(fd, "#define SYMBOL_STRING(sym) #sym\n"); + fprintf(fd, "\n"); + fprintf(fd, "static struct ltt_facility facility = {\n"); + fprintf(fd, "\t.name = ltt_facility_name,\n"); + fprintf(fd, "\t.num_events = LTT_FACILITY_NUM_EVENTS,\n"); + fprintf(fd, "\t.checksum = LTT_FACILITY_CHECKSUM,\n"); + fprintf(fd, "\t.symbol = SYMBOL_STRING(LTT_FACILITY_SYMBOL),\n"); + fprintf(fd, "};\n"); + fprintf(fd, "\n"); + fprintf(fd, "static int __init facility_init(void)\n"); + fprintf(fd, "{\n"); + fprintf(fd, "\tprintk(KERN_INFO \"LTT : ltt-facility-%s init in kernel\\n\");\n", fac->name); + fprintf(fd, "\n"); + fprintf(fd, "\tLTT_FACILITY_SYMBOL = ltt_facility_kernel_register(&facility);\n"); + fprintf(fd, "\tLTT_FACILITY_CHECKSUM_SYMBOL = LTT_FACILITY_SYMBOL;\n"); + fprintf(fd, "\t\n"); + fprintf(fd, "\treturn LTT_FACILITY_SYMBOL;\n"); + fprintf(fd, "}\n"); + fprintf(fd, "\n"); + fprintf(fd, "#ifndef MODULE\n"); + fprintf(fd, "__initcall(facility_init);\n"); + fprintf(fd, "#else\n"); + fprintf(fd, "module_init(facility_init);\n"); + fprintf(fd, "static void __exit facility_exit(void)\n"); + fprintf(fd, "{\n"); + fprintf(fd, "\tint err;\n"); + fprintf(fd, "\n"); + fprintf(fd, "\terr = ltt_facility_unregister(LTT_FACILITY_SYMBOL);\n"); + fprintf(fd, "\tif (err != 0)\n"); + fprintf(fd, "\t\tprintk(KERN_ERR \"LTT : Error in unregistering facility.\\n\");\n"); + fprintf(fd, "\n"); + fprintf(fd, "}\n"); + fprintf(fd, "module_exit(facility_exit)\n"); + fprintf(fd, "\n"); + fprintf(fd, "MODULE_LICENSE(\"GPL\");\n"); + fprintf(fd, "MODULE_AUTHOR(\"Mathieu Desnoyers\");\n"); + fprintf(fd, "MODULE_DESCRIPTION(\"Linux Trace Toolkit Facility\");\n"); + fprintf(fd, "\n"); + fprintf(fd, "#endif //MODULE\n"); + fprintf(fd, "\n"); + fprintf(fd, "#endif //CONFIG_LTT\n"); + + fclose(fd); + + return 0; +} + +int print_loader_c_user(facility_t *fac) +{ + char filename[PATH_MAX]; + unsigned int filename_size = 0; + FILE *fd; + dprintf("%s\n", fac->name); + + strcpy(filename, "ltt-facility-loader-"); + filename_size = strlen(filename); + + strncat(filename, fac->name, PATH_MAX - filename_size); + filename_size = strlen(filename); + + if(fac->arch) { + strncat(filename, "_", PATH_MAX - filename_size); + filename_size = strlen(filename); + + strncat(filename, fac->arch, PATH_MAX - filename_size); + filename_size = strlen(filename); + } + + strncat(filename, ".c", PATH_MAX - filename_size); + filename_size = strlen(filename); + + + fd = fopen(filename, "w"); + if(fd == NULL) { + printf("Error opening file %s for writing : %s\n", + filename, strerror(errno)); + return errno; + } + + fprintf(fd, "/*\n"); + if(!fac->arch) + fprintf(fd, " * ltt-facility-loader-%s.c\n", fac->name); + else + fprintf(fd, " * ltt-facility-loader-%s_%s.c\n", fac->name, fac->arch); + fprintf(fd, " *\n"); + fprintf(fd, " * (C) Copyright 2005 - \n"); + fprintf(fd, " * Mathieu Desnoyers (mathieu.desnoyers@polymtl.ca)\n"); + fprintf(fd, " *\n"); + fprintf(fd, " * Contains the LTT user space facility loader.\n"); + fprintf(fd, " *\n"); + fprintf(fd, " */\n"); + fprintf(fd, "\n"); + fprintf(fd, "\n"); + fprintf(fd, "#define LTT_TRACE\n"); + fprintf(fd, "#include \n"); + fprintf(fd, "#include \n"); + fprintf(fd, "#include \n"); + if(!fac->arch) + fprintf(fd, "#include \"ltt-facility-loader-%s.h\"\n", fac->name); + else + fprintf(fd, "#include \"ltt-facility-loader-%s_%s.h\"\n", + fac->name, fac->arch); + fprintf(fd, "\n"); + fprintf(fd, "static struct user_facility_info facility = {\n"); + fprintf(fd, "\t.name = LTT_FACILITY_NAME,\n"); + fprintf(fd, "\t.num_events = LTT_FACILITY_NUM_EVENTS,\n"); + fprintf(fd, "#ifndef LTT_PACK\n"); + fprintf(fd, "\t.alignment = sizeof(void*),\n"); + fprintf(fd, "#else\n"); + fprintf(fd, "\t.alignment = 0,\n"); + fprintf(fd, "#endif //LTT_PACK\n"); + fprintf(fd, "\t.checksum = LTT_FACILITY_CHECKSUM,\n"); + fprintf(fd, "\t.int_size = sizeof(int),\n"); + fprintf(fd, "\t.long_size = sizeof(long),\n"); + fprintf(fd, "\t.pointer_size = sizeof(void*),\n"); + fprintf(fd, "\t.size_t_size = sizeof(size_t)\n"); + fprintf(fd, "};\n"); + fprintf(fd, "\n"); + fprintf(fd, "static void __attribute__((constructor)) __ltt_user_init(void)\n"); + fprintf(fd, "{\n"); + fprintf(fd, "\tint err;\n"); + fprintf(fd, "#ifdef LTT_SHOW_DEBUG\n"); + fprintf(fd, "\tprintf(\"LTT : ltt-facility-%s init in userspace\\n\");\n", fac->name); + fprintf(fd, "#endif //LTT_SHOW_DEBUG\n"); + fprintf(fd, "\n"); + fprintf(fd, "\terr = ltt_register_generic(<T_FACILITY_SYMBOL, &facility);\n"); + fprintf(fd, "\tLTT_FACILITY_CHECKSUM_SYMBOL = LTT_FACILITY_SYMBOL;\n"); + fprintf(fd, "\t\n"); + fprintf(fd, "\tif (err) {\n"); + fprintf(fd, "#ifdef LTT_SHOW_DEBUG\n"); + fprintf(fd, "\t\tperror(\"Error in ltt_register_generic\");\n"); + fprintf(fd, "#endif //LTT_SHOW_DEBUG\n"); + fprintf(fd, "\t}\n"); + fprintf(fd, "}\n"); + fprintf(fd, "\n"); + + fclose(fd); + + return 0; +} + + + +/* open facility */ +/* code taken from ltt_facility_open in ltt/facility.c in lttv */ + /***************************************************************************** *Function name - * generateLoaderfile: generate a facility loaded .h file - *Input Params - * fp : file to be written to - * facName : name of facility - * nbEvent : number of events in the facility - * checksum : checksum for the facility + * ltt_facility_open : open facilities + *Input params + * pathname : the path name of the facility + * + * Open the facility corresponding to the right checksum. + * + *returns the facility on success, NULL on error. ****************************************************************************/ -void generateLoaderfile(FILE * fp, char * facName, int nbEvent, unsigned long checksum){ - //will be removed later - fprintf(fp,"ltt_facility_t\tltt_facility_%s_%X;\n\n", facName, checksum); - - fprintf(fp,"EXPORT_SYMBOL(ltt_facility_%s_%X);\n\n",facName, checksum); - fprintf(fp,"#define LTT_FACILITY_SYMBOL\t\t\t\tltt_facility_%s_%X\n", - facName, checksum); - fprintf(fp,"#define LTT_FACILITY_CHECKSUM\t\t\t0x%X\n", checksum); - fprintf(fp,"#define LTT_FACILITY_NAME\t\t\t\t\t\"%s\"\n", facName); - fprintf(fp,"#define LTT_FACILITY_NUM_EVENTS\t\t%d\n\n", nbEvent); +facility_t *ltt_facility_open(char * pathname) +{ + int ret = 0; + char *token; + parse_file_t in; + facility_t * fac = NULL; + char buffer[BUFFER_SIZE]; + int generated = FALSE; + + in.buffer = &(buffer[0]); + in.lineno = 0; + in.error = error_callback; + in.name = pathname; + in.unget = 0; + + in.fp = fopen(in.name, "r"); + if(in.fp == NULL) { + ret = 1; + goto open_error; + } + + while(1){ + token = getToken(&in); + if(in.type == ENDFILE) break; + + if(generated) { + printf("More than one facility in the file. Only using the first one.\n"); + break; + } + + if(strcmp(token, "<")) in.error(&in,"not a facility file"); + token = getName(&in); + if(strcmp(token, "?")) in.error(&in,"not a facility file"); + token = getName(&in); + if(strcmp(token, "xml")) in.error(&in,"not a facility file"); + token = getName(&in); + if(strcmp(token, "version")) in.error(&in,"not a facility file"); + token = getName(&in); + if(strcmp(token, "=")) in.error(&in,"not a facility file"); + token = getQuotedString(&in); + if(strcmp(token, "1.0")) in.error(&in,"not a facility file"); + token = getName(&in); + if(strcmp(token, "?")) in.error(&in,"not a facility file"); + token = getToken(&in); + if(strcmp(token, ">")) in.error(&in,"not a facility file"); + + token = getName(&in); + if(strcmp(token, "<")) in.error(&in,"not a facility file"); + token = getName(&in); + if(strcmp("facility",token) == 0) { + fac = malloc(sizeof(facility_t)); + fac->name = NULL; + fac->description = NULL; + sequence_init(&(fac->events)); + table_init(&(fac->named_types)); + sequence_init(&(fac->unnamed_types)); + + parseFacility(&in, fac); + + //check if any namedType is not defined + checkNamedTypesImplemented(&fac->named_types); + + generateChecksum(fac->name, &fac->checksum, &fac->events); + + generated = TRUE; + } + else { + printf("facility token was expected in file %s\n", in.name); + ret = 1; + goto parse_error; + } + } + + parse_error: + fclose(in.fp); +open_error: + + if(!generated) { + printf("Cannot find facility %s\n", pathname); + fac = NULL; + } + + return fac; +} + +/* Close the facility */ +void ltt_facility_close(facility_t *fac) +{ + free(fac->name); + free(fac->capname); + free(fac->description); + freeEvents(&fac->events); + sequence_dispose(&fac->events); + freeNamedType(&fac->named_types); + table_dispose(&fac->named_types); + freeTypes(&fac->unnamed_types); + sequence_dispose(&fac->unnamed_types); + free(fac); +} + + +/* Show help */ +void show_help(int argc, char ** argv) +{ + printf("Genevent help : \n"); + printf("\n"); + printf("Use %s name.xml\n", argv[0]); + printf("to create :\n"); + printf("ltt-facility-name.h\n"); + printf("ltt-facility-id-name.h\n"); + printf("ltt-facility-loader-name.h\n"); + printf("ltt-facility-loader-name.c\n"); + printf("In the current directory.\n"); + printf("\n"); +} + +/* Parse program arguments */ +/* Return values : + * 0 : continue program + * -1 : stop program, return 0 + * > 0 : stop program, return value as exit. + */ +int check_args(int argc, char **argv) +{ + if(argc < 2) { + printf("Not enough arguments\n"); + show_help(argc, argv); + return EINVAL; + } + + if(strcmp(argv[1], "-h") == 0) { + show_help(argc, argv); + return -1; + } + + return 0; +} + +int main(int argc, char **argv) +{ + int err = 0; + facility_t *fac; + + err = check_args(argc, argv); + if(err > 0) return err; + else if(err < 0) return 0; + + /* open the facility */ + fac = ltt_facility_open(argv[1]); + if(fac == NULL) { + printf("Error opening file %s for reading : %s\n", + argv[1], strerror(errno)); + return errno; + } + + /* generate the output C files */ + + + /* ltt-facility-name.h : main logging header. + * log_header */ + err = print_log_header(fac); + if(err) return err; + + /* ltt-facility-id-name.h : facility id. + * log_id_header */ + err = print_id_header(fac); + if(err) return err; + + /* ltt-facility-loader-name.h : facility specific loader info. + * loader_header */ + if(!fac->user) + err = print_loader_header(fac); + else + err = print_loader_header_user(fac); + if(err) return err; + + /* ltt-facility-loader-name.c : generic faciilty loader + * loader_c */ + if(!fac->user) + err = print_loader_c(fac); + else + err = print_loader_c_user(fac); + if(err) return err; + + /* close the facility */ + ltt_facility_close(fac); + + return 0; }