* to know the structure's alignment.
*/
+#define _GNU_SOURCE
+#include <limits.h>
+#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
-#include <stdlib.h>
+#include <assert.h>
#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
+
+
/* Code printing */
+void print_tabs(unsigned int tabs, FILE *fd)
+{
+ for(unsigned int i = 0; i<tabs;i++)
+ fprintf(fd, "\t");
+}
+
/* Type size checking */
+/* Uses #error in the generated code to signal error and stop the compiler */
int print_check(int fd);
int print_events(int fd);
+/* print type.
+ *
+ * Copied from construct_types_and_fields in LTTV facility.c */
+
+int print_type(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) {
+ 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, "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, "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 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;
+
+ 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) {
+ strncat(basename, "_", PATH_MAX - basename_len);
+ basename_len = strlen(basename);
+ }
+ strncat(basename, field_name, PATH_MAX - basename_len);
+ dprintf("%s\n", field_name);
+ }
+
+ switch(td->type) {
+ case ENUM:
+ fprintf(fd, "enum lttng_%s", basename);
+ fprintf(fd, " {\n");
+ for(unsigned int i=0;i<td->labels.position;i++){
+ print_tabs(1, fd);
+ fprintf(fd, "LTTNG_%s", ((char*)(td->labels.array[i])));
+ fprintf(fd, ",\n");
+ }
+ fprintf(fd, "};\n");
+ fprintf(fd, "\n");
+ break;
+
+ case ARRAY:
+ assert(td->size >= 0);
+ if(td->nested_type->type_name == NULL) {
+ /* Not a named nested type : we must print its declaration first */
+ if(print_type_declaration(td->nested_type,
+ fd, 0, basename, "")) return 1;
+ }
+ fprintf(fd, "#define LTTNG_ARRAY_SIZE_%s %llu\n", basename,
+ td->size);
+ print_type(td->nested_type, fd, tabs, basename, "");
+ fprintf(fd, " lttng_array_%s[LTTNG_ARRAY_SIZE_%s];\n", basename,
+ basename);
+ fprintf(fd, "\n");
+ break;
+ case SEQUENCE:
+ if(td->nested_type->type_name == NULL) {
+ /* Not a named nested type : we must print its declaration first */
+ if(print_type_declaration(td->nested_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);
+ fprintf(fd, "unsigned int len;\n");
+ print_tabs(1, fd);
+ print_type(td->nested_type, fd, tabs, basename, "");
+ fprintf(fd, " *array;\n");
+ fprintf(fd, "};\n");
+ fprintf(fd, "\n");
+ break;
+
+ case STRUCT:
+ for(unsigned int i=0;i<td->fields.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;i<td->fields.position;i++){
+ field_t *field = (field_t*)(td->fields.array[i]);
+ type_descriptor_t *type = field->type;
+ print_tabs(1, fd);
+ print_type(type, fd, tabs, basename, field->name);
+ fprintf(fd, " ");
+ fprintf(fd, "%s", field->name);
+ fprintf(fd, ";\n");
+ }
+ fprintf(fd, "};\n");
+ fprintf(fd, "\n");
+ break;
+ case UNION:
+ /* TODO : Do not allow variable length fields in a union */
+ for(unsigned int i=0;i<td->fields.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;i<td->fields.position;i++){
+ field_t *field = (field_t*)(td->fields.array[i]);
+ type_descriptor_t *type = field->type;
+ print_tabs(1, fd);
+ print_type(type, fd, tabs, basename, field->name);
+ fprintf(fd, " ");
+ fprintf(fd, "%s", field->name);
+ fprintf(fd, ";\n");
+ }
+ fprintf(fd, "};\n");
+ fprintf(fd, "\n");
+ break;
+ default:
+ dprintf("print_type_declaration : unknown type or nothing to declare.\n");
+ break;
+ }
+
+ 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);
+}
+
+
+
+
+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;
+ }
+ return 0;
+}
+
+int print_log_header_events(facility_t *fac, FILE *fd)
+{
+
+ return 0;
+}
+
+
+void print_log_header_tail(facility_t *fac, FILE *fd)
+{
+ 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);
+
+ 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 */
+ print_log_header_head(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 */
+ print_log_header_tail(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;
+ 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);
+
+ 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;
+ }
+
+ 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);
+
+ 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;
+ }
+
+ fclose(fd);
+
+ return 0;
+}
+
+/* ltt-facility-loader-name.c : generic faciilty 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);
+
+ 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;
+ }
+
+
+ fclose(fd);
+
+ return 0;
+}
+
+
+
/* open facility */
/* code taken from ltt_facility_open in ltt/facility.c in lttv */
/* generate the output C files */
- /* ltt-facility-name.h : main logging header */
-
+ /* 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. */
+ /* 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. */
-
- /* ltt-facility-loader-name.c : generic faciilty loader */
-
-
+ /* ltt-facility-loader-name.h : facility specific loader info.
+ * loader_header */
+ err = print_loader_header(fac);
+ if(err) return err;
+
+ /* ltt-facility-loader-name.c : generic faciilty loader
+ * loader_c */
+ err = print_loader_c(fac);
+ if(err) return err;
/* close the facility */
ltt_facility_close(fac);
#include "parser.h"
-static char *intOutputTypes[] = {
- "int8_t", "int16_t", "int32_t", "int64_t", "short int", "int", "long int" };
+char *intOutputTypes[] = {
+ "int8_t", "int16_t", "int32_t", "int64_t" };
-static char *uintOutputTypes[] = {
- "uint8_t", "uint16_t", "uint32_t", "uint64_t", "unsigned short int",
- "unsigned int", "unsigned long int" };
+char *uintOutputTypes[] = {
+ "uint8_t", "uint16_t", "uint32_t", "uint64_t" };
-static char *floatOutputTypes[] = {
- "undef", "undef", "float", "double", "undef", "float", "double" };
+char *floatOutputTypes[] = {
+ "undef", "undef", "float", "double" };
}
-int getSizeindex(int value)
+int getSizeindex(unsigned int value)
{
switch(value) {
case 1:
* size
*****************************************************************************/
-int getSize(parse_file_t *in)
+unsigned long long int getSize(parse_file_t *in)
{
char *token;
token = getToken(in);
if(in->type == NUMBER) {
- if(strcmp(token,"1") == 0) return 0;
- else if(strcmp(token,"2") == 0) return 1;
- else if(strcmp(token,"4") == 0) return 2;
- else if(strcmp(token,"8") == 0) return 3;
- }
- else if(in->type == NAME) {
- if(strcmp(token,"short") == 0) return 4;
- else if(strcmp(token,"medium") == 0) return 5;
- else if(strcmp(token,"long") == 0) return 6;
+ return strtoull(token, NULL, 0);
}
in->error(in,"incorrect size specification");
return -1;
char * token;
t->fmt = NULL;
- t->size = -1;
+ t->size = 0;
t->alignment = 0;
while(1) {
// 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)) {
+ } else if(!strcmp("size",token) || !strcmp("lengthsize", token)) {
getEqual(in);
t->size = getSize(in);
} else if(!strcmp("align",token)) {
else if(strcmp(token,"union") == 0) {
t->type = UNION;
getTypeAttributes(in, t);
- if(t->size == -1) in->error(in, "Union has empty size");
- getRAnglebracket(in); //<union typecodesize=isize>
+ getRAnglebracket(in); //<union>
getLAnglebracket(in); //<field name=..>
token = getToken(in);
else if(strcmp(token,"array") == 0) {
t->type = ARRAY;
getTypeAttributes(in, t);
- if(t->size == -1) in->error(in, "Array has empty size");
+ if(t->size == 0) in->error(in, "Array has empty size");
+ getForwardslash(in);
getRAnglebracket(in); //<array size=n>
getLAnglebracket(in); //<type struct>
else if(strcmp(token,"sequence") == 0) {
t->type = SEQUENCE;
getTypeAttributes(in, t);
- if(t->size == -1) in->error(in, "Sequence has empty size");
- getRAnglebracket(in); //<array lengthsize=isize>
+ if(t->size == 0) in->error(in, "Sequence has empty lengthsize");
+ getForwardslash(in);
+ getRAnglebracket(in); //<sequence lengthsize=isize>
getLAnglebracket(in); //<type struct>
t->nested_type = parseType(in,NULL, unnamed_types, named_types);
sequence_init(&(t->labels_description));
t->already_printed = 0;
getTypeAttributes(in, t);
- if(t->size == -1) in->error(in, "Sequence has empty size");
+ //if(t->size == 0) in->error(in, "Sequence has empty size");
+ //Mathieu : we fix enum size to 4 bytes. GCC is always like this.
+ //fox copy optimisation.
+ if(t->size != 0) in->error(in, "Enum has fixed size of 4.");
+ t->size = 4;
getRAnglebracket(in);
//<label name=label1 value=n/>
if(strcmp("enum",token))in->error(in, "not a valid enum definition");
getRAnglebracket(in); //</label>
}
+ else if(strcmp(token,"int_fixed") == 0) {
+ t->type = INT_FIXED;
+ getTypeAttributes(in, t);
+ if(t->size == 0) in->error(in, "int has empty size");
+ getForwardslash(in);
+ getRAnglebracket(in);
+ }
+ else if(strcmp(token,"uint_fixed") == 0) {
+ t->type = UINT_FIXED;
+ getTypeAttributes(in, t);
+ if(t->size == 0) in->error(in, "uint has empty size");
+ getForwardslash(in);
+ getRAnglebracket(in);
+ }
+ else if(strcmp(token,"char") == 0) {
+ t->type = CHAR;
+ getTypeAttributes(in, t);
+ getForwardslash(in);
+ getRAnglebracket(in);
+ }
+ else if(strcmp(token,"uchar") == 0) {
+ t->type = UCHAR;
+ getTypeAttributes(in, t);
+ getForwardslash(in);
+ getRAnglebracket(in);
+ }
+ else if(strcmp(token,"short") == 0) {
+ t->type = SHORT;
+ getTypeAttributes(in, t);
+ getForwardslash(in);
+ getRAnglebracket(in);
+ }
+ else if(strcmp(token,"ushort") == 0) {
+ t->type = USHORT;
+ getTypeAttributes(in, t);
+ getForwardslash(in);
+ getRAnglebracket(in);
+ }
else if(strcmp(token,"int") == 0) {
t->type = INT;
getTypeAttributes(in, t);
- if(t->size == -1) in->error(in, "int has empty size");
getForwardslash(in);
getRAnglebracket(in);
}
else if(strcmp(token,"uint") == 0) {
t->type = UINT;
getTypeAttributes(in, t);
- if(t->size == -1) in->error(in, "uint has empty size");
getForwardslash(in);
getRAnglebracket(in);
}
+
else if(strcmp(token,"pointer") == 0) {
t->type = POINTER;
getTypeAttributes(in, t);
char *token;
token = getToken(in);
- if(in->type != FORWARDSLASH) in->error(in, "forward slash token was expected");
+ //if(in->type != FORWARDSLASH) in->error(in, "forward slash token was expected");
+ /* Mathieu : final / is optional now. */
+ if(in->type != FORWARDSLASH) ungetToken(in);
+
return token;
}
field_t * fld;
switch(type->type){
- case INT:
- str = intOutputTypes[type->size];
+ case INT_FIXED:
+ str = intOutputTypes[getSizeindex(type->size)];
break;
- case UINT:
- str = uintOutputTypes[type->size];
+ case UINT_FIXED:
+ str = uintOutputTypes[getSizeindex(type->size)];
break;
case POINTER:
str = allocAndCopy("void *");
flag = 1;
break;
+ case CHAR:
+ str = allocAndCopy("signed char");
+ flag = 1;
+ break;
+ case UCHAR:
+ str = allocAndCopy("unsigned char");
+ flag = 1;
+ break;
+ case SHORT:
+ str = allocAndCopy("short");
+ flag = 1;
+ break;
+ case USHORT:
+ str = allocAndCopy("unsigned short");
+ flag = 1;
+ break;
+ case INT:
+ str = allocAndCopy("int");
+ flag = 1;
+ break;
+ case UINT:
+ str = allocAndCopy("uint");
+ flag = 1;
+ break;
case LONG:
str = allocAndCopy("long");
flag = 1;
flag = 1;
break;
case FLOAT:
- str = floatOutputTypes[type->size];
+ str = floatOutputTypes[getSizeindex(type->size)];
break;
case STRING:
str = allocAndCopy("string");
flag = 1;
break;
case ENUM:
- str = appendString("enum ", uintOutputTypes[type->size]);
+ //str = appendString("enum ", uintOutputTypes[getSizeindex(type->size)]);
+ str = allocAndCopy("enum");
flag = 1;
break;
case ARRAY:
- sprintf(buf,"%d",type->size);
+ sprintf(buf,"%llu", type->size);
str = appendString("array ",buf);
flag = 1;
break;
case SEQUENCE:
- sprintf(buf,"%d",type->size);
+ sprintf(buf,"%llu", type->size);
str = appendString("sequence ",buf);
flag = 1;
break;