From: compudj Date: Wed, 21 Jan 2009 22:25:06 +0000 (+0000) Subject: move genevent to attic X-Git-Tag: v0.12.20~245 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=61adf092014cafc70e5a910b48e7be6110da73f9;p=lttv.git move genevent to attic git-svn-id: http://ltt.polymtl.ca/svn@3244 04897980-b3bd-0310-b5e0-8ef037075253 --- diff --git a/trunk/attic/genevent/Makefile b/trunk/attic/genevent/Makefile new file mode 100644 index 00000000..5947dc2a --- /dev/null +++ b/trunk/attic/genevent/Makefile @@ -0,0 +1,27 @@ +SHELL = /bin/sh + +CC = gcc + +#CFLAGS = -std=c99 -Wall -g -DDEBUG +CFLAGS = -std=c99 -Wall -g + +all: genevent + +install: genevent + cp -f genevent /usr/local/bin + +genevent: genevent.o parser.o + $(CC) $(CFLAGS) -o $@ $^ + +genevent.o: genevent.c genevent.h parser.h + $(CC) $(CFLAGS) -c -o $@ $< + +parser.o: parser.c parser.h + $(CC) $(CFLAGS) -c -o $@ $< + +.PHONY: clean + +clean: + rm -rf *.o *~ *# genevent + + diff --git a/trunk/attic/genevent/README b/trunk/attic/genevent/README new file mode 100644 index 00000000..d38633d3 --- /dev/null +++ b/trunk/attic/genevent/README @@ -0,0 +1,101 @@ + +Mathieu Desnoyers -- November 2005 + +This is a complete rework of genevent. + +The 'genevent' program parses event descriptions and generates +the inline functions to record events in the kernel. + +There are several files in the directory: + genevent.c, genevent.h, crc32.tab, parser.c and parser.h + +In fact, crc32.tab, parser.c and parser.h are the same files as +those in LTT library. + +Important notes : + * Do not put "-" symbols in facilities name. + * Use the exact same name for facility xml file and for facility name. + * As from genevent 0.17, a standard XML 1.0 description is "required". It must + begin with the header. + +Note about strings : +There are three methods to write strings in genevent, each suitable and +efficient for a particular case. They are explained here from the fastest +to the slowest. +1 - The C code presents a fixed size string. + For example, you find : + char mystring[10]; + as string definition. + + you must then define it as an array of char : + + + Note, however, that you might not want to declare a fixed size for trace size + and unnecessary copy matters. + + For instance, on a 32 bits architecture, copying a n bytes array takes + approximately* n/4 memory read and write, for n/2 memory operations. + + Using the slower method described in (3), with a strlen and memcpy, where + "u" is the number of used caracters, takes u+1 reads for the strlen, and + approximately* (u+1)/4 read and write for the memcpy, for a total of : + (3/2)*(u+1) memory access. + + So, if (n/2) > (3/2)*(u+1), or : n > 3*u+3 + where n is the size of the array + u is the average number of used caracters (excluding the \0) + it becomes faster to use the method number 3 with strlen. + +2 - The C code presents a variable size string together with its + size. + + A typical use for this case is filenames in the Linux kernel. The + dentry strucure has a d_name member, which is a struct qstr containing + a unsigned int len and const unsigned char *name. + + you must use a sequence to declare this efficiently : + + +3 - The C code presents a \0 terminated string. + + This is the slowest, but most convenient way to declare a string. You are + discouraged to use it when options 1 or 2 are available. It will dynamically + calculate the string length (byte by byte read) and only afterward do a + memcpy. + + Note that, as explained in 1, if n > 3*u+3, it becomes faster to use this + method instead of copying the whole fixed size array. + + Declare like this : + + +Here is a brief description of how to use genevent. + +make +make install + + +* Add new events to the kernel with genevent + +su - +cd /usr/local/share/LinuxTraceToolkitViewer/facilities +cp process.xml yourfacility.xml + * edit yourfacility.xml to fit your needs. +cd /tmp +/usr/local/bin/genevent /usr/local/share/LinuxTraceToolkitViewer/yourfacility.xml +cp ltt-facility-yourfacility.h ltt-facility-id-yourfacility.h \ + /usr/src/linux-2.6.12-rc4-mm2-lttng-0.2/include/linux/ltt +cp ltt-facility-loader-yourfacility.c ltt-facility-loader-yourfacility.h \ + /usr/src/linux-2.6.12-rc4-mm2-lttng-0.2/ltt + * edit the kernel file you want to instrument + - Add #include at the beginning + of the file. + - Add a call to the tracing functions. See their names and parameters in + /usr/src/linux-2.6.12-rc4-mm2-lttng-0.2/include/linux/ltt/ltt-facility-yourfacility.h + + + +* The approximation comes from the fact that copies of number of caracters non + multiple of the architecture size takes more operations (maximum of : + (architecture size (in bytes) - 1) operations). + diff --git a/trunk/attic/genevent/crc32.tab b/trunk/attic/genevent/crc32.tab new file mode 100644 index 00000000..d0174ad6 --- /dev/null +++ b/trunk/attic/genevent/crc32.tab @@ -0,0 +1,52 @@ + 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, + 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U, + 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, + 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, + 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U, + 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U, + 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, + 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, + 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, + 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU, + 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, + 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, + 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U, + 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, + 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, + 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U, + 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU, + 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U, + 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, + 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, + 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU, + 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U, + 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U, + 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU, + 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, + 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U, + 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U, + 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U, + 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U, + 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU, + 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, + 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U, + 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, + 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU, + 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU, + 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U, + 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU, + 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, + 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, + 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U, + 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU, + 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U, + 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, + 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, + 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U, + 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U, + 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U, + 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U, + 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, + 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U, + 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, + 0x2d02ef8dU diff --git a/trunk/attic/genevent/genevent.c b/trunk/attic/genevent/genevent.c new file mode 100644 index 00000000..fd7b2b73 --- /dev/null +++ b/trunk/attic/genevent/genevent.c @@ -0,0 +1,3050 @@ +/****************************************************************************** + * 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 + +#include "genevent.h" +#include "parser.h" + + +#define TRUE 1 +#define FALSE (!TRUE) + +/* Debugging printf */ +#ifdef DEBUG +#define dprintf(...) \ + do {\ + printf(__FILE__ ",%u,%s: ",\ + __LINE__, __func__);\ + printf(__VA_ARGS__);\ + } while(0) +#else +#define dprintf(...) +#endif + + +enum user_fct_types { USER_FCT_PROTO, USER_FCT_DECLARATION } ; + +/* Code printing */ + +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); + } + + 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; +} + +/* 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); + } + + 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; + } + + return 0; +} + + +/* 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"); + } + if(td->fac->align) + fprintf(fd, "} LTT_ALIGN;\n"); + else + fprintf(fd, "};\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"); + } + if(td->fac->align) + fprintf(fd, "} LTT_ALIGN;\n"); + else + fprintf(fd, "};\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(td->fac->align) { + if(print_type_alignment(td, fd, 0, basename, "", "obj")) return 1; + } else + fprintf(fd, "0"); + 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 */ + if(td->fac->align == 0) return 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[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(td->fac->align) { + if(print_type_alignment(td, fd, 0, basename, "", "obj")) return 1; + } else + fprintf(fd, "0"); + 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); + if(td->fac->align) + 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); + if(td->fac->align) + 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; + } + + /* 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"); + fprintf(fd, "\n"); + + if(!event->force) { + 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"); + if(!event->force) { + 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"); + /* 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 */ + if(strcmp("compact", fac->name) != 0) { + print_tabs(2, fd); + fprintf(fd, "buffer = 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, tsc);\n"); + } else { + print_tabs(2, fd); + fprintf(fd, "buffer = ltt_write_compact_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); + if(event->compact_data) { + assert(event->fields.position > 0); + field_t *field = (field_t*)(event->fields.array[0]); + fprintf(fd, "reserve_size, tsc, lttng_param_%s);\n", + field->name); + } else + fprintf(fd, "reserve_size, tsc, 0);\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; + + /* First param is compacted in the header */ + if(event->compact_data && i == 0) + continue; + /* 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; + + 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"); + } + +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); + + print_tabs(1, fd); + fprintf(fd, "}\n\n"); + + print_tabs(1, fd); + fprintf(fd, "return ret;\n\n"); + + fprintf(fd, "}\n"); + fprintf(fd, + "#endif //LTT_TRACE\n"); + fprintf(fd, "#endif //!LTT_TRACE_FAST\n\n"); + + return 0; +} + +/* 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); + + 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"); + /* 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, "buffer = 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, tsc);\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; +} + + + + + + +/* ltt-facility-name.h : main logging header. + * log_header */ + +void print_log_header_head(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"); +} + +/* 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"); +} + + +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(((type_descriptor_t*)types->array[i])->fac->align) + 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) +{ + 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(fac->align) { + 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; +} + + +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); + } + + 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; + } + + /* 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; +} + + +/* 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; +} + + +/* 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,"extern unsigned int ltt_get_channel_index_%s(u8 eID);\n\n", + fac->name); + + 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,"#define LTT_FACILITY_ALIGNMENT\t\t%u\n\n", + fac->align); + fprintf(fd,"#define LTT_FACILITY_SELECT\t\tltt_get_channel_index_%s\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,"#define LTT_FACILITY_ALIGNMENT\t\t\t\t\t%u\n\n", + fac->align); + 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, "\t.alignment = LTT_FACILITY_ALIGNMENT,\n"); + fprintf(fd, "\t.select = LTT_FACILITY_SELECT,\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 = LTT_FACILITY_ALIGNMENT?sizeof(void*):0,\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 + * 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. + ****************************************************************************/ +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; +} + + diff --git a/trunk/attic/genevent/genevent.h b/trunk/attic/genevent/genevent.h new file mode 100644 index 00000000..4515c758 --- /dev/null +++ b/trunk/attic/genevent/genevent.h @@ -0,0 +1,66 @@ +/****************************************************************************** + * Genevent + * + * Event generator. XML to logging C code converter. + * + * 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. + */ + + + +/* Code printing */ + +/* Type size checking */ +int print_check(int fd); + + +/* Print types */ +int print_types(int fd); + +/* Print events */ +int print_events(int fd); + + + diff --git a/trunk/attic/genevent/gentest.c b/trunk/attic/genevent/gentest.c new file mode 100644 index 00000000..753ac4d7 --- /dev/null +++ b/trunk/attic/genevent/gentest.c @@ -0,0 +1,485 @@ + +#define __KERNEL__ + +#include +#include +#include +#include +#include + +#include + +#define min(a,b) (((a)<(b))?a:b) +#define max(a,b) (((a)>(b))?a:b) +#define BUG_ON(a) assert(!(a)) + +// Useful outside __KERNEL__. Not used here because inline is already redefined. +#define force_inline inline __attribute__((always_inline)) + +/* Calculate the offset needed to align the type */ +static inline unsigned int ltt_align(size_t align_drift, + size_t size_of_type) +{ + size_t alignment = min(sizeof(void*), size_of_type); + + return ((alignment - align_drift) & (alignment-1)); +} + + +/* TEMPLATE */ + +enum lttng_tasklet_priority { + LTTNG_LOW, + LTTNG_HIGH, +}; + +enum lttng_irq_mode { + LTTNG_user, + LTTNG_kernel, +}; + +struct lttng_mystruct2 { + unsigned int irq_id; + enum lttng_irq_mode mode; + //struct lttng_mystruct teststr1; +}; + +#if 0 +static inline size_t lttng_get_size_mystruct2( + struct lttng_mystruct2 * obj) +{ + size_t size=0, locsize; + + locsize = sizeof(unsigned int); + size += ltt_align(size, locsize) + locsize; + + locsize = sizeof(enum lttng_irq_mode); + size += ltt_align(size, locsize) + locsize; + + BUG_ON(sizeof(struct lttng_mystruct2) != size); + + return sizeof(struct lttng_mystruct2); +} +#endif //0 + +static inline size_t lttng_get_alignment_mystruct2( + struct lttng_mystruct2 *obj) +{ + size_t align=0, localign; + + localign = sizeof(unsigned int); + align = max(align, localign); + + localign = sizeof(enum lttng_irq_mode); + align = max(align, localign); + + return align; +} + +static inline void lttng_write_mystruct2( + void *buffer, + size_t *to_base, + size_t *to, + void **from, + size_t *len, + struct lttng_mystruct2 *obj) +{ + size_t align, size; + + align = lttng_get_alignment_mystruct2(obj); + //size = lttng_get_size_mystruct2(obj); + size = sizeof(struct lttng_mystruct2); + + if(*len == 0) { + *to += ltt_align(*to, align); /* align output */ + } else { + *len += ltt_align(*to+*len, align); /* C alignment, ok to do a memcpy of it */ + } + + *len += size; +} + + + +#define LTTNG_ARRAY_SIZE_mystruct_myarray 10 +typedef uint64_t lttng_array_mystruct_myarray[LTTNG_ARRAY_SIZE_mystruct_myarray]; + +#if 0 +static inline size_t lttng_get_size_array_mystruct_myarray( + lttng_array_mystruct_myarray obj) +{ + size_t size=0, locsize; + + locsize = sizeof(uint64_t); + /* ltt_align == 0 always*/ + //size += ltt_align(size, locsize) + (LTTNG_ARRAY_SIZE_mystruct_myarray * locsize); + BUG_ON(ltt_align(size, locsize) != 0); + size += LTTNG_ARRAY_SIZE_mystruct_myarray * locsize; + + BUG_ON(sizeof(lttng_array_mystruct_myarray) != size); + + return sizeof(lttng_array_mystruct_myarray); +} +#endif //0 + +static inline size_t lttng_get_alignment_array_mystruct_myarray( + lttng_array_mystruct_myarray obj) +{ + size_t align=0, localign; + + localign = sizeof(uint64_t); + align = max(align, localign); + + return align; +} + + +static inline void lttng_write_array_mystruct_myarray( + void *buffer, + size_t *to_base, + size_t *to, + void **from, + size_t *len, + lttng_array_mystruct_myarray obj) +{ + size_t align, size; + + align = lttng_get_alignment_array_mystruct_myarray(obj); + //size = lttng_get_size_array_mystruct_myarray(obj); + size = sizeof(lttng_array_mystruct_myarray); + + if(*len == 0) { + *to += ltt_align(*to, align); /* align output */ + } else { + *len += ltt_align(*to+*len, align); /* C alignment, ok to do a memcpy of it */ + } + + *len += size; +#if 0 + /* For varlen child : let the child align itself. */ + for(unsigned int i=0; ilen * locsize); + + /* Realign on arch size */ + locsize = sizeof(void *); + size += ltt_align(size, locsize); + + return size; +} +#endif //0 + +static inline size_t lttng_get_alignment_sequence_mystruct_mysequence( + lttng_sequence_mystruct_mysequence *obj) +{ + size_t align=0, localign; + + localign = sizeof(unsigned int); + align = max(align, localign); + + localign = sizeof(double); + align = max(align, localign); + + return align; +} + + +static inline void lttng_write_sequence_mystruct_mysequence( + void *buffer, + size_t *to_base, + size_t *to, + void **from, + size_t *len, + lttng_sequence_mystruct_mysequence *obj) +{ + size_t align; + size_t size; + + /* Flush pending memcpy */ + if(*len != 0) { + if(buffer != NULL) + memcpy(buffer+*to_base+*to, *from, *len); + } + *to += *len; + *len = 0; + + align = lttng_get_alignment_sequence_mystruct_mysequence(obj); + //no need size = lttng_get_size_sequence_mystruct_mysequence(obj); + + /* Align output */ + *to += ltt_align(*to, align); /* *len = 0 in this function */ + + /* Copy members */ + size = sizeof(unsigned int); + *to += ltt_align(*to, size); + if(buffer != NULL) + memcpy(buffer+*to_base+*to, &obj->len, size); + *to += size; + + size = sizeof(double); + *to += ltt_align(*to, size); + size = obj->len * sizeof(double); + if(buffer != NULL) + memcpy(buffer+*to_base+*to, obj->array, size); + *to += size; +#if 0 + /* If varlen child : let child align itself */ + for(unsigned int i=0; ilen; i++) { + lttng_write_child(buffer, to_base, to, from, len, obj->array[i]); + } +#endif //0 + + + /* Realign the *to_base on arch size, set *to to 0 */ + *to = ltt_align(*to, sizeof(void *)); + *to_base = *to_base+*to; + *to = 0; + + /* Put source *from just after the C sequence */ + *from = obj+1; +} + + + +union lttng_mystruct_myunion { + double myfloat; + unsigned long myulong; +}; + +#if 0 +static inline size_t lttng_get_size_mystruct_myunion( + union lttng_mystruct_myunion *obj) +{ + size_t size=0, locsize; + + locsize = sizeof(double); + size = max(size, locsize); + + locsize = sizeof(unsigned long); + size = max(size, locsize); + + BUG_ON(size != sizeof(union lttng_mystruct_myunion)); + + return sizeof(union lttng_mystruct_myunion); +} +#endif //0 + +static inline size_t lttng_get_alignment_mystruct_myunion( + union lttng_mystruct_myunion *obj) +{ + size_t align=0, localign; + + localign = sizeof(double); + align = max(align, localign); + + localign = sizeof(unsigned long); + align = max(align, localign); + + return align; +} + + +static inline void lttng_write_mystruct_myunion( + void *buffer, + size_t *to_base, + size_t *to, + void **from, + size_t *len, + union lttng_mystruct_myunion *obj) +{ + size_t align, size; + + align = lttng_get_alignment_mystruct_myunion(obj); + //size = lttng_get_size_mystruct_myunion(obj); + size = sizeof(union lttng_mystruct_myunion); + + if(*len == 0) { + *to += ltt_align(*to, align); /* align output */ + } else { + *len += ltt_align(*to+*len, align); /* C alignment, ok to do a memcpy of it */ + } + + *len += size; + + /* Assert : no varlen child. */ +} + + +struct lttng_mystruct { + unsigned int irq_id; + enum lttng_irq_mode mode; + struct lttng_mystruct2 teststr; + lttng_array_mystruct_myarray myarray; + lttng_sequence_mystruct_mysequence mysequence; + union lttng_mystruct_myunion myunion; +}; + +#if 0 +static inline size_t lttng_get_size_mystruct( + struct lttng_mystruct *obj) +{ + size_t size=0, locsize, localign; + + locsize = sizeof(unsigned int); + size += ltt_align(size, locsize) + locsize; + + locsize = sizeof(enum lttng_irq_mode); + size += ltt_align(size, locsize) + locsize; + + localign = lttng_get_alignment_mystruct2(&obj->teststr); + locsize = lttng_get_size_mystruct2(&obj->teststr); + size += ltt_align(size, localign) + locsize; + + localign = lttng_get_alignment_array_mystruct_myarray(obj->myarray); + locsize = lttng_get_size_array_mystruct_myarray(obj->myarray); + size += ltt_align(size, localign) + locsize; + + localign = lttng_get_alignment_sequence_mystruct_mysequence(&obj->mysequence); + locsize = lttng_get_size_sequence_mystruct_mysequence(&obj->mysequence); + size += ltt_align(size, localign) + locsize; + + localign = lttng_get_alignment_mystruct_myunion(&obj->myunion); + locsize = lttng_get_size_mystruct_myunion(&obj->myunion); + size += ltt_align(size, localign) + locsize; + + return size; +} +#endif //0 + +static inline size_t lttng_get_alignment_mystruct( + struct lttng_mystruct *obj) +{ + size_t align=0, localign; + + localign = sizeof(unsigned int); + align = max(align, localign); + + localign = sizeof(enum lttng_irq_mode); + align = max(align, localign); + + localign = lttng_get_alignment_mystruct2(&obj->teststr); + align = max(align, localign); + + localign = lttng_get_alignment_array_mystruct_myarray(obj->myarray); + align = max(align, localign); + + localign = lttng_get_alignment_sequence_mystruct_mysequence(&obj->mysequence); + align = max(align, localign); + + localign = lttng_get_alignment_mystruct_myunion(&obj->myunion); + align = max(align, localign); + + return align; +} + +static inline void lttng_write_mystruct( + void *buffer, + size_t *to_base, + size_t *to, + void **from, + size_t *len, + struct lttng_mystruct *obj) +{ + size_t align, size; + + align = lttng_get_alignment_mystruct(obj); + // no need : contains variable size fields. + // locsize = lttng_get_size_mystruct(obj); + + if(*len == 0) { + *to += ltt_align(*to, align); /* align output */ + } else { + *len += ltt_align(*to+*len, align); /* C alignment, ok to do a memcpy of it */ + } + + /* Contains variable sized fields : must explode the structure */ + + size = sizeof(unsigned int); + size += ltt_align(*to+*len, size) + size; + *len += size; + + size = sizeof(enum lttng_irq_mode); + size += ltt_align(*to+*len, size) + size; + *len += size; + + lttng_write_mystruct2(buffer, to_base, to, from, len, &obj->teststr); + + lttng_write_array_mystruct_myarray(buffer, to_base, to, from, len, obj->myarray); + + /* Variable length field */ + lttng_write_sequence_mystruct_mysequence(buffer, to_base, to, from, len, &obj->mysequence); + /* After this previous write, we are sure that *to is 0, *len is 0 and + * *to_base is aligned on the architecture size : to rest of alignment will + * be calculated statically. */ + + lttng_write_mystruct_myunion(buffer, to_base, to, from, len, &obj->myunion); + + /* Don't forget to flush last write..... */ +} + + + + + + +//void main() +void test() +{ + struct lttng_mystruct test; + test.mysequence.len = 20; + test.mysequence.array = malloc(20); + + //size_t size = lttng_get_size_mystruct(&test); + //size_t align = lttng_get_alignment_mystruct(&test); + // + size_t to_base = 0; /* the buffer is allocated on arch_size alignment */ + size_t to = 0; + void *from = &test; + size_t len = 0; + + /* Get size */ + lttng_write_mystruct(NULL, &to_base, &to, &from, &len, &test); + /* Size = to_base + to + len */ + + void *buffer = malloc(to_base + to + len); + to_base = 0; /* the buffer is allocated on arch_size alignment */ + to = 0; + from = &test; + len = 0; + + lttng_write_mystruct(buffer, &to_base, &to, &from, &len, &test); + /* Final flush */ + /* Flush pending memcpy */ + if(len != 0) { + // Assert buffer != NULL */ + memcpy(buffer+to_base+to, from, len); + to += len; + from += len; + len = 0; + } + + free(test.mysequence.array); + free(buffer); +} diff --git a/trunk/attic/genevent/ltt-facility-test-template.h b/trunk/attic/genevent/ltt-facility-test-template.h new file mode 100644 index 00000000..b5efa41c --- /dev/null +++ b/trunk/attic/genevent/ltt-facility-test-template.h @@ -0,0 +1,551 @@ +#ifndef _LTT_FACILITY_TEST_H_ +#define _LTT_FACILITY_TEST_H_ + + +/* Facility activation at compile time. */ +#ifdef CONFIG_LTT_FACILITY_TEST + +/* Named types */ + + +enum lttng_tasklet_priority { + LTTNG_LOW, + LTTNG_HIGH, +}; + +enum lttng_irq_mode { + LTTNG_user, + LTTNG_kernel, +}; + +struct lttng_mystruct2 { + unsigned int irq_id; + enum lttng_irq_mode mode; + //struct lttng_mystruct teststr1; +}; + + +size_t lttng_get_size_mystruct2( + struct lttng_mystruct2 *obj) +{ + size_t size=0, locsize; + + locsize = sizeof(unsigned int); + size += ltt_align(size, locsize) + locsize; + + locsize = sizeof(enum lttng_irq_mode); + size += ltt_align(size, locsize) + locsize; + + BUG_ON(sizeof(struct lttng_mystruct2) != size); + + return sizeof(struct lttng_mystruct2); +} + +size_t lttng_get_alignment_mystruct2( + struct lttng_mystruct2 *obj) +{ + size_t align=0, localign; + + localign = sizeof(unsigned int); + align = max(align, localign); + + localign = sizeof(enum lttng_irq_mode); + align = max(align, localign); + + return align; +} + +void lttng_write_mystruct2(void **to, + void **from, + size_t *len, + struct lttng_mystruct2 *obj) +{ + size_t align, size; + + align = lttng_get_alignment_mystruct2(obj); + size = lttng_get_size_mystruct2(obj); + + if(*len == 0) { + *to += ltt_align((size_t)(*to), align); /* align output */ + } else { + *len += ltt_align((size_t)(*to+*len), align); /* C alignment, ok to do a memcpy of it */ + } + + *len += size; +} + + + +#define LTTNG_ARRAY_SIZE_mystruct_myarray 10 +typedef uint64_t lttng_array_mystruct_myarray[LTTNG_ARRAY_SIZE_mystruct_myarray]; + +size_t lttng_get_size_array_mystruct_myarray( + lttng_array_mystruct_myarray obj) +{ + size_t size=0, locsize; + + locsize = sizeof(uint64_t); + /* ltt_align == 0 always*/ + //size += ltt_align(size, locsize) + (LTTNG_ARRAY_SIZE_mystruct_myarray * locsize); + BUG_ON(ltt_align(size, locsize) != 0); + size += LTTNG_ARRAY_SIZE_mystruct_myarray * locsize; + + BUG_ON(size != LTTNG_ARRAY_SIZE_mystruct_myarray * sizeof(uint64_t)); + + return size; +} + +size_t lttng_get_alignment_array_mystruct_myarray( + lttng_array_mystruct_myarray obj) +{ + size_t align=0, localign; + + localign = sizeof(uint64_t); + align = max(align, localign); + + return align; +} + + +void lttng_write_array_mystruct_myarray(void **to, + void **from, + size_t *len, + lttng_array_mystruct_myarray obj) +{ + size_t align, size; + + align = lttng_get_alignment_array_mystruct_myarray(obj); + size = lttng_get_size_array_mystruct_myarray(obj); + + if(*len == 0) { + *to += ltt_align((size_t)(*to), align); /* align output */ + } else { + *len += ltt_align((size_t)(*to+*len), align); /* C alignment, ok to do a memcpy of it */ + } + + *len += size; +} + + +typedef struct lttng_sequence_mystruct_mysequence lttng_sequence_mystruct_mysequence; +struct lttng_sequence_mystruct_mysequence { + unsigned int len; + double *array; +}; + + +size_t lttng_get_size_sequence_mystruct_mysequence( + lttng_sequence_mystruct_mysequence *obj) +{ + size_t size=0, locsize; + + locsize = sizeof(unsigned int); + size += ltt_align(size, locsize) + locsize; + + locsize = sizeof(double); + size += ltt_align(size, locsize) + (obj->len * locsize); + + return size; +} + +size_t lttng_get_alignment_sequence_mystruct_mysequence( + lttng_sequence_mystruct_mysequence *obj) +{ + size_t align=0, localign; + + localign = sizeof(unsigned int); + align = max(align, localign); + + localign = sizeof(double); + align = max(align, localign); + + return align; +} + + +void lttng_write_sequence_mystruct_mysequence(void **to, + void **from, + size_t *len, + lttng_sequence_mystruct_mysequence *obj) +{ + size_t align, size; + void *varfrom; + size_t varlen=0; + + /* Flush pending memcpy */ + if(*len != 0) { + memcpy(*to, *from, *len); + *to += *len; + *len = 0; + } + + align = lttng_get_alignment_sequence_mystruct_mysequence(obj); + //no need size = lttng_get_size_sequence_mystruct_mysequence(obj); + + /* Align output */ + *to += ltt_align((size_t)(*to), align); + + /* Copy members */ + *to += ltt_align((size_t)*to, sizeof(unsigned int)); + varfrom = &obj->len; + varlen += sizeof(unsigned int); + memcpy(*to, varfrom, varlen); + *to += varlen; + varlen = 0; + + *to += ltt_align((size_t)*to, sizeof(double)); + varfrom = obj->array; + varlen += obj->len * sizeof(double); + memcpy(*to, varfrom, varlen); + *to += varlen; + varlen = 0; + + /* Put source *from just after the C sequence */ + *from = obj+1; +} + + + +union lttng_mystruct_myunion { + double myfloat; + unsigned long myulong; +}; + + +size_t lttng_get_size_mystruct_myunion( + union lttng_mystruct_myunion *obj) +{ + size_t size=0, locsize; + + locsize = sizeof(double); + size = max(size, locsize); + + locsize = sizeof(unsigned long); + size = max(size, locsize); + + BUG_ON(size != sizeof(union lttng_mystruct_myunion)); + + return size; +} + + +size_t lttng_get_alignment_mystruct_myunion( + union lttng_mystruct_myunion *obj) +{ + size_t align=0, localign; + + localign = sizeof(double); + align = max(align, localign); + + localign = sizeof(unsigned long); + align = max(align, localign); + + return align; +} + + +void lttng_write_mystruct_myunion(void **to, + void **from, + size_t *len, + union lttng_mystruct_myunion *obj) +{ + size_t align, size; + + align = lttng_get_alignment_mystruct_myunion(obj); + size = lttng_get_size_mystruct_myunion(obj); + + if(*len == 0) { + *to += ltt_align((size_t)(*to), align); /* align output */ + } else { + *len += ltt_align((size_t)(*to+*len), align); /* C alignment, ok to do a memcpy of it */ + } + + *len += size; +} + + +struct lttng_mystruct { + unsigned int irq_id; + enum lttng_irq_mode mode; + struct lttng_mystruct2 teststr; + lttng_array_mystruct_myarray myarray; + lttng_sequence_mystruct_mysequence mysequence; + union lttng_mystruct_myunion myunion; +}; + +size_t lttng_get_size_mystruct( + struct lttng_mystruct *obj) +{ + size_t size=0, locsize, localign; + + locsize = sizeof(unsigned int); + size += ltt_align(size, locsize) + locsize; + + locsize = sizeof(enum lttng_irq_mode); + size += ltt_align(size, locsize) + locsize; + + localign = lttng_get_alignment_mystruct2(&obj->teststr); + locsize = lttng_get_size_mystruct2(&obj->teststr); + size += ltt_align(size, localign) + locsize; + + localign = lttng_get_alignment_array_mystruct_myarray(obj->myarray); + locsize = lttng_get_size_array_mystruct_myarray(obj->myarray); + size += ltt_align(size, localign) + locsize; + + localign = lttng_get_alignment_sequence_mystruct_mysequence(&obj->mysequence); + locsize = lttng_get_size_sequence_mystruct_mysequence(&obj->mysequence); + size += ltt_align(size, localign) + locsize; + + localign = lttng_get_alignment_mystruct_myunion(&obj->myunion); + locsize = lttng_get_size_mystruct_myunion(&obj->myunion); + size += ltt_align(size, localign) + locsize; + + return size; +} + + +size_t lttng_get_alignment_mystruct( + struct lttng_mystruct *obj) +{ + size_t align=0, localign; + + localign = sizeof(unsigned int); + align = max(align, localign); + + localign = sizeof(enum lttng_irq_mode); + align = max(align, localign); + + localign = lttng_get_alignment_mystruct2(&obj->teststr); + align = max(align, localign); + + localign = lttng_get_alignment_array_mystruct_myarray(obj->myarray); + align = max(align, localign); + + localign = lttng_get_alignment_sequence_mystruct_mysequence(&obj->mysequence); + align = max(align, localign); + + localign = lttng_get_alignment_mystruct_myunion(&obj->myunion); + align = max(align, localign); + + return align; +} + +void lttng_write_mystruct(void **to, + void **from, + size_t *len, + struct lttng_mystruct *obj) +{ + size_t align, size; + + align = lttng_get_alignment_mystruct(obj); + // no need : contains variable size fields. + // locsize = lttng_get_size_mystruct(obj); + + if(*len == 0) { + *to += ltt_align((size_t)(*to), align); /* align output */ + } else { + *len += ltt_align((size_t)(*to+*len), align); /* C alignment, ok to do a memcpy of it */ + } + + /* Contains variable sized fields : must explode the structure */ + + size = sizeof(unsigned int); + *len += ltt_align((size_t)(*to+*len), size) + size; + + size = sizeof(enum lttng_irq_mode); + *len += ltt_align((size_t)(*to+*len), size) + size; + + lttng_write_mystruct2(to, from, len, &obj->teststr); + + lttng_write_array_mystruct_myarray(to, from, len, obj->myarray); + + /* Variable length field */ + lttng_write_sequence_mystruct_mysequence(to, from, len, &obj->mysequence); + + lttng_write_mystruct_myunion(to, from, len, &obj->myunion); + + /* Don't forget to flush last write..... */ +} + + + + +/* Event syscall_entry structures */ + +/* Event syscall_entry logging function */ +static inline void trace_test_syscall_entry( + unsigned int syscall_id, + void * address) +#ifndef CONFIG_LTT +{ +} +#else +{ +} +#endif //CONFIG_LTT + + +/* Event syscall_exit structures */ + +/* Event syscall_exit logging function */ +static inline void trace_test_syscall_exit( + void) +#ifndef CONFIG_LTT +{ +} +#else +{ +} +#endif //CONFIG_LTT + + +/* Event trap_entry structures */ + +/* Event trap_entry logging function */ +static inline void trace_test_trap_entry( + unsigned int trap_id, + void * address) +#ifndef CONFIG_LTT +{ +} +#else +{ +} +#endif //CONFIG_LTT + + +/* Event trap_exit structures */ + +/* Event trap_exit logging function */ +static inline void trace_test_trap_exit( + void) +#ifndef CONFIG_LTT +{ +} +#else +{ +} +#endif //CONFIG_LTT + + +/* Event soft_irq_entry structures */ + +/* Event soft_irq_entry logging function */ +static inline void trace_test_soft_irq_entry( + void * softirq_id) +#ifndef CONFIG_LTT +{ +} +#else +{ +} +#endif //CONFIG_LTT + + +/* Event soft_irq_exit structures */ + +/* Event soft_irq_exit logging function */ +static inline void trace_test_soft_irq_exit( + void * softirq_id) +#ifndef CONFIG_LTT +{ +} +#else +{ +} +#endif //CONFIG_LTT + + +/* Event tasklet_entry structures */ + +/* Event tasklet_entry logging function */ +static inline void trace_test_tasklet_entry( + enum lttng_tasklet_priority priority, + void * address, + unsigned long data) +#ifndef CONFIG_LTT +{ +} +#else +{ +} +#endif //CONFIG_LTT + + +/* Event tasklet_exit structures */ + +/* Event tasklet_exit logging function */ +static inline void trace_test_tasklet_exit( + enum lttng_tasklet_priority priority, + void * address, + unsigned long data) +#ifndef CONFIG_LTT +{ +} +#else +{ +} +#endif //CONFIG_LTT + + +/* Event irq_entry structures */ + +/* Event irq_entry logging function */ +static inline void trace_test_irq_entry( + unsigned int irq_id, + enum lttng_irq_mode mode) +#ifndef CONFIG_LTT +{ +} +#else +{ +} +#endif //CONFIG_LTT + + +/* Event irq_exit structures */ + +/* Event irq_exit logging function */ +static inline void trace_test_irq_exit( + void) +#ifndef CONFIG_LTT +{ +} +#else +{ +} +#endif //CONFIG_LTT + + +/* Event big_array structures */ +union lttng_test_big_array_myarray_b { + void * c; +}; + +struct lttng_test_big_array_myarray { + void * a; + union lttng_test_big_array_myarray_b b; +}; + +#define LTTNG_ARRAY_SIZE_test_big_array_myarray 2 +typedef struct lttng_test_big_array_myarray lttng_array_test_big_array_myarray[LTTNG_ARRAY_SIZE_test_big_array_myarray]; + +#define LTTNG_ARRAY_SIZE_test_big_array_myarray 10000 +typedef lttng_array_test_big_array_myarray lttng_array_test_big_array_myarray[LTTNG_ARRAY_SIZE_test_big_array_myarray]; + + +/* Event big_array logging function */ +static inline void trace_test_big_array( + lttng_array_test_big_array_myarray myarray) +#ifndef CONFIG_LTT +{ +} +#else +{ +} +#endif //CONFIG_LTT + + +#endif //CONFIG_LTT_FACILITY_TEST + +#endif //_LTT_FACILITY_TEST_H_ diff --git a/trunk/attic/genevent/parser.c b/trunk/attic/genevent/parser.c new file mode 100644 index 00000000..7ac11e7e --- /dev/null +++ b/trunk/attic/genevent/parser.c @@ -0,0 +1,1670 @@ + + + +/* + +parser.c: Generate helper declarations and functions to trace events + from an event description file. + + Copyright (C) 2005, Mathieu Desnoyers + 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 ".xml" event definitions input files + and constructs structure for each event. + + 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 ".xml" file is finished. */ + +#include +#include +#include +#include +#include +#include +#include + +#include "parser.h" + + +char *intOutputTypes[] = { + "int8_t", "int16_t", "int32_t", "int64_t" }; + +char *uintOutputTypes[] = { + "uint8_t", "uint16_t", "uint32_t", "uint64_t" }; + +char *floatOutputTypes[] = { + "undef", "undef", "float", "double" }; + + + + +/* helper function */ +void strupper(char *string) +{ + char *ptr = string; + + while(*ptr != '\0') { + *ptr = toupper(*ptr); + ptr++; + } +} + + +int getSizeindex(unsigned int value) +{ + switch(value) { + case 1: + return 0; + case 2: + return 1; + case 4: + return 2; + case 8: + return 3; + default: + printf("Error : unknown value size %d\n", value); + exit(-1); + } +} + +/***************************************************************************** + *Function name + * getSize : translate from string to integer + *Input params + * in : input file handle + *Return values + * size + *****************************************************************************/ + +unsigned long long int getSize(parse_file_t *in) +{ + char *token, *token2; + unsigned long long int ret; + + token = getToken(in); + + + if(in->type == QUOTEDSTRING) { + in->type = NUMBER; + token2 = token; + do { + if (!isdigit(*token2)) { + in->type = QUOTEDSTRING; + break; + } + } while (*(++token2) != '\0'); + } + + if(in->type == NUMBER) { + ret = strtoull(token, NULL, 0); + } else { + goto error; + } + + return ret; +error: + in->error(in,"incorrect size specification"); + return -1; +} + +/***************************************************************************** + *Function name + * error_callback : print out error info + *Input params + * in : input file handle + * msg : message to be printed + ****************************************************************************/ + +void error_callback(parse_file_t *in, char *msg) +{ + if(in) + printf("Error in file %s, line %d: %s\n", in->name, in->lineno, msg); + else + printf("%s\n",msg); + assert(0); + exit(1); +} + +/***************************************************************************** + *Function name + * memAlloc : allocate memory + *Input params + * size : required memory size + *return value + * void * : pointer to allocate memory or NULL + ****************************************************************************/ + +void * memAlloc(int size) +{ + void * addr; + if(size == 0) return NULL; + addr = malloc(size); + if(!addr){ + printf("Failed to allocate memory"); + exit(1); + } + return addr; +} + +/***************************************************************************** + *Function name + * allocAndCopy : allocate memory and initialize it + *Input params + * str : string to be put in memory + *return value + * char * : pointer to allocate memory or NULL + ****************************************************************************/ + +char *allocAndCopy(char *str) +{ + char * addr; + if(str == NULL) return NULL; + addr = (char *)memAlloc(strlen(str)+1); + strcpy(addr,str); + return addr; +} + +/************************************************************************** + * Function : + * getTypeAttributes + * Description : + * Read the attribute from the input file. + * + * Parameters : + * in , input file handle. + * t , the type descriptor to fill. + * + **************************************************************************/ + +void getTypeAttributes(parse_file_t *in, type_descriptor_t *t, + sequence_t * unnamed_types, table_t * named_types) +{ + char * token; + int car; + + t->fmt = NULL; + t->size = 0; + t->custom_write = 0; + t->network = 0; + + while(1) { + token = getToken(in); + if(strcmp("/",token) == 0 || strcmp(">",token) == 0){ + ungetToken(in); + break; + } + + if(!strcmp("format",token)) { + getEqual(in); + t->fmt = allocAndCopy(getQuotedString(in)); + // printf("%s - ",t->fmt); + //} else if(!strcmp("name",token)) { + // getEqual(in); + // car = seekNextChar(in); + // if(car == EOF) in->error(in,"name was expected"); + // else if(car == '\"') t->type_name = allocAndCopy(getQuotedString(in)); + // else t->type_name = allocAndCopy(getName(in)); + } else if(!strcmp("size",token)) { + getEqual(in); + t->size = getSize(in); + } else if(!strcmp("custom_write", token)) { + t->custom_write = 1; + } else if(!strcmp("byte_order",token)) { + getEqual(in); + car = seekNextChar(in); + if(car == EOF) in->error(in,"byte order was expected (network?)"); + else if(car == '\"') token = getQuotedString(in); + else token = getName(in); + if(!strcmp("network", token)) { + t->network = 1; + } + } else if(!strcmp("write",token)) { + getEqual(in); + car = seekNextChar(in); + if(car == EOF) in->error(in,"write type was expected (custom?)"); + else if(car == '\"') token = getQuotedString(in); + else token = getName(in); + if(!strcmp("custom", token)) { + t->custom_write = 1; + } + } + } +} + +/************************************************************************** + * Function : + * getEventAttributes + * Description : + * Read the attribute from the input file. + * + * Parameters : + * in , input file handle. + * ev , the event to fill. + * + **************************************************************************/ + +void getEventAttributes(parse_file_t *in, event_t *ev) +{ + char * token; + int car; + + ev->name = NULL; + ev->per_trace = 0; + ev->per_tracefile = 0; + ev->param_buffer = 0; + ev->no_instrument_function = 0; + ev->high_priority = 0; + ev->force = 0; + ev->compact_data = 0; + + while(1) { + token = getToken(in); + if(strcmp("/",token) == 0 || strcmp(">",token) == 0){ + ungetToken(in); + break; + } + + if(!strcmp("name",token)) { + getEqual(in); + car = seekNextChar(in); + if(car == EOF) in->error(in,"name was expected"); + else if(car == '\"') ev->name = allocAndCopy(getQuotedString(in)); + else ev->name = allocAndCopy(getName(in)); + } else if(!strcmp("scope", token)) { + getEqual(in); + car = seekNextChar(in); + if(car == EOF) in->error(in,"scope was expected"); + else if(car == '\"') token = getQuotedString(in); + else token = getName(in); + if(!strcmp(token, "trace")) ev->per_trace = 1; + else if(!strcmp(token, "tracefile")) ev->per_tracefile = 1; + } else if(!strcmp("param", token)) { + getEqual(in); + car = seekNextChar(in); + if(car == EOF) in->error(in,"parameter type was expected"); + else if(car == '\"') token = getQuotedString(in); + else token = getName(in); + if(!strcmp(token, "buffer")) ev->param_buffer = 1; + } else if(!strcmp("attribute", token)) { + getEqual(in); + car = seekNextChar(in); + if(car == EOF) in->error(in,"attribute was expected"); + else if(car == '\"') token = getQuotedString(in); + else token = getName(in); + if(!strcmp(token, "no_instrument_function")) + ev->no_instrument_function = 1; + else if(!strcmp(token, "high_priority")) + ev->high_priority = 1; + else if(!strcmp(token, "force")) + ev->force = 1; + else if(!strcmp(token, "compact_data")) + ev->compact_data = 1; + } + } +} + +/************************************************************************** + * Function : + * getFacilityAttributes + * Description : + * Read the attribute from the input file. + * + * Parameters : + * in , input file handle. + * fac , the facility to fill. + * + **************************************************************************/ + +void getFacilityAttributes(parse_file_t *in, facility_t *fac) +{ + char * token; + int car; + + fac->name = NULL; + fac->arch = NULL; + fac->align = 1; + fac->user = 0; + + while(1) { + token = getToken(in); + if(strcmp("/",token) == 0 || strcmp(">",token) == 0){ + ungetToken(in); + break; + } + + if(!strcmp("name",token)) { + getEqual(in); + car = seekNextChar(in); + if(car == EOF) in->error(in,"name was expected"); + else if(car == '\"') fac->name = allocAndCopy(getQuotedString(in)); + else fac->name = allocAndCopy(getName(in)); + if(!strncmp(fac->name, "user_", sizeof("user_")-1)) + fac->user = 1; + } else if(!strcmp("arch", token)) { + getEqual(in); + car = seekNextChar(in); + if(car == '\"') fac->arch = allocAndCopy(getQuotedString(in)); + else fac->arch = allocAndCopy(getName(in)); + } else if(!strcmp("align", token)) { + getEqual(in); + fac->align = getSize(in); + } + + } +} + +/************************************************************************** + * Function : + * getFieldAttributes + * Description : + * Read the attribute from the input file. + * + * Parameters : + * in , input file handle. + * f , the field to fill. + * + **************************************************************************/ + +void getFieldAttributes(parse_file_t *in, field_t *f) +{ + char * token; + int car; + + f->name = NULL; + + while(1) { + token = getToken(in); + if(strcmp("/",token) == 0 || strcmp(">",token) == 0){ + ungetToken(in); + break; + } + + if(!strcmp("name",token)) { + getEqual(in); + car = seekNextChar(in); + if(car == EOF) in->error(in,"name was expected"); + else if(car == '\"') f->name = allocAndCopy(getQuotedString(in)); + else f->name = allocAndCopy(getName(in)); + } + } +} + +char *getNameAttribute(parse_file_t *in) +{ + char * token; + char *name = NULL; + int car; + + while(1) { + token = getToken(in); + if(!strcmp("name",token)) { + getEqual(in); + car = seekNextChar(in); + if(car == EOF) in->error(in,"name was expected"); + else if(car == '\"') name = allocAndCopy(getQuotedString(in)); + else name = allocAndCopy(getName(in)); + } else { + ungetToken(in); + break; + } + + } + if(name == NULL) in->error(in, "Name was expected"); + return name; +} + + + +//for