+
+/* 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 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);
+ }
+
+ 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(&obj->%s)", basename,
+ field_name);
+ break;
+ case STRUCT:
+ fprintf(fd, "lttng_get_alignment_struct_%s(&obj->%s)", basename,
+ field_name);
+ break;
+ case UNION:
+ fprintf(fd, "lttng_get_alignment_union_%s(&obj->%s)", basename,
+ field_name);
+ break;
+ case ARRAY:
+ fprintf(fd, "lttng_get_alignment_array_%s(obj->%s)", basename,
+ 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 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[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:
+ 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, "size = ");
+ fprintf(fd, "sizeof(");
+ if(print_type(td, fd, 0, basename, "")) return 1;
+ fprintf(fd, ");\n");
+ print_tabs(tabs, fd);
+ fprintf(fd, "size += ltt_align(*to+*len, size) + size;\n");
+ print_tabs(tabs, fd);
+ fprintf(fd, "*len += size;");
+ break;
+ case STRING:
+ print_tabs(tabs, fd);
+ fprintf(fd, "lttng_write_string_%s(buffer, to_base, to, from, len, obj->%s);\n", basename, field_name);
+ break;
+ case SEQUENCE:
+ print_tabs(tabs, fd);
+ fprintf(fd, "lttng_write_%s(buffer, to_base, to, from, len, &obj->%s)", basename,
+ field_name);
+ break;
+ case STRUCT:
+ print_tabs(tabs, fd);
+ fprintf(fd, "lttng_write_struct_%s(buffer, to_base, to, from, len, &obj->%s)", basename,
+ field_name);
+ break;
+ case UNION:
+ print_tabs(tabs, fd);
+ fprintf(fd, "lttng_write_union_%s(buffer, to_base, to, from, len, &obj->%s)", basename,
+ field_name);
+ break;
+ case ARRAY:
+ print_tabs(tabs, fd);
+ fprintf(fd, "lttng_write_array_%s(buffer, to_base, to, from, len, obj->%s)", basename,
+ field_name);
+ 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;
+
+ 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:
+ /* 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, ((field_t*)td->fields.array[0])->name)) 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, ((field_t*)td->fields.array[1])->name)) 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:
+ /* 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;i<td->fields.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)) 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:
+ /* 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;i<td->fields.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)) 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:
+ /* 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, ((field_t*)td->fields.array[0])->name)) return 1;
+ fprintf(fd, ";\n");
+ break;
+ default:
+ printf("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;
+
+ 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:
+ case STRUCT:
+ case UNION:
+ case ARRAY:
+ break;
+ default:
+ printf("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;
+ default:
+ printf("print_type_write_fct : type has no write function.\n");
+ break;
+ }
+
+ print_tabs(2, fd);
+ fprintf(fd, "void *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, "void **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;
+ default:
+ printf("print_type_write_fct : type has no write function.\n");
+ break;
+ }
+
+ fprintf(fd, "{\n");
+ print_tabs(1, fd);
+ fprintf(fd, "size_t align, size;\n");
+ fprintf(fd, "\n");
+
+ switch(td->type) {
+ case SEQUENCE:
+ case STRING:
+ print_tabs(1, fd);
+ fprintf(fd, "/* Flush pending memcpy */\n");
+ print_tabs(1, fd);
+ fprintf(fd, "if(*len != 0) {\n");
+ print_tabs(2, fd);
+ fprintf(fd, "if(buffer != NULL)\n");
+ print_tabs(3, fd);
+ fprintf(fd, "memcpy(buffer+*to_base+*to, *from, *len);\n");
+ print_tabs(1, fd);
+ fprintf(fd, "}\n");
+ print_tabs(1, fd);
+ fprintf(fd, "*to += *len;\n");
+ print_tabs(1, fd);
+ fprintf(fd, "*len = 0;\n");
+ fprintf(fd, "\n");
+ break;
+ case STRUCT:
+ case UNION:
+ case ARRAY:
+ break;
+ default:
+ printf("print_type_write_fct : type has no write function.\n");
+ break;
+ }
+
+ print_tabs(1, fd);
+ fprintf(fd, "align = ");
+ if(print_type_alignment(td, fd, 0, basename, field_name)) return 1;
+ fprintf(fd, ";\n");
+ fprintf(fd, "\n");
+ print_tabs(1, fd);
+ fprintf(fd, "if(*len == 0) {\n");
+ print_tabs(2, fd);
+ fprintf(fd, "*to += ltt_align(*to, align); /* align output */\n");
+ print_tabs(1, fd);
+ fprintf(fd, "} else {\n");
+ print_tabs(2, fd);
+ fprintf(fd, "*len += ltt_align(*to+*len, align); /* alignment, ok to do a memcpy of it */\n");
+ print_tabs(1, fd);
+ fprintf(fd, "}\n");
+ fprintf(fd, "\n");
+
+ /* First, check if the type has a fixed size. If it is the case, then the size
+ * to write is know by the compiler : simply use a sizeof() */
+ if(has_type_fixed_size(td)) {
+ print_tabs(1, fd);
+ fprintf(fd, "/* Contains only fixed size fields : use compiler sizeof() */\n");
+ fprintf(fd, "\n");
+ print_tabs(1, fd);
+ fprintf(fd, "*len += sizeof(");
+ if(print_type(td, fd, 0, basename, field_name)) return 1;
+ fprintf(fd, ");\n");
+ } else {
+ /* The type contains nested variable size subtypes :
+ * we must write field by field. */
+ print_tabs(1, fd);
+ fprintf(fd, "/* Contains variable sized fields : must explode the structure */\n");
+ fprintf(fd, "\n");
+
+ switch(td->type) {
+ case SEQUENCE:
+ print_tabs(1, fd);
+ fprintf(fd, "/* Copy members */\n");
+ print_tabs(1, fd);
+ fprintf(fd, "size = sizeof(\n");
+ if(print_type_write(((field_t*)td->fields.array[0])->type,
+ fd, 1, basename, ((field_t*)td->fields.array[0])->name)) return 1;
+ 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, size);\n");
+ print_tabs(1, fd);
+ fprintf(fd, "*to += size;\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");
+ if(print_type_write(((field_t*)td->fields.array[1])->type,
+ fd, 1, basename, ((field_t*)td->fields.array[1])->name)) return 1;
+ fprintf(fd, ");\n");
+ print_tabs(1, fd);
+ fprintf(fd, "*to += ltt_align(*to, size);\n");
+ print_tabs(1, fd);
+ fprintf(fd, "size = obj->len * size;\n");
+ print_tabs(1, fd);
+ fprintf(fd, "if(buffer != NULL)\n");
+ print_tabs(2, fd);
+ fprintf(fd, "memcpy(buffer+*to_base+*to, obj->array, size);\n");
+ print_tabs(1, fd);
+ fprintf(fd, "*to += size;\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, ((field_t*)td->fields.array[1])->name)) return 1;
+ print_tabs(1, fd);
+ fprintf(fd, "}\n");
+ }
+ fprintf(fd, "\n");
+ print_tabs(1, fd);
+ fprintf(fd, "/* Realign the *to_base on arch size, set *to to 0 */\n");
+ print_tabs(1, fd);
+ fprintf(fd, "*to = ltt_align(*to, sizeof(void *));\n");
+ print_tabs(1, fd);
+ fprintf(fd, "*to_base = *to_base+*to;\n");
+ print_tabs(1, fd);
+ fprintf(fd, "*to = 0;\n");
+ fprintf(fd, "\n");
+ fprintf(fd, "/* Put source *from just after the C sequence */\n");
+ print_tabs(1, fd);
+ fprintf(fd, "*from = obj+1;\n");
+ break;
+ case STRING:
+ fprintf(fd, "size = strlen(obj);\n");
+ print_tabs(1, fd);
+ fprintf(fd, "if(buffer != NULL)\n");
+ print_tabs(2, fd);
+ fprintf(fd, "memcpy(buffer+*to_base+*to, obj, size);\n");
+ print_tabs(1, fd);
+ fprintf(fd, "*to += size;\n");
+ fprintf(fd, "\n");
+ print_tabs(1, fd);
+ fprintf(fd, "/* Realign the *to_base on arch size, set *to to 0 */\n");
+ print_tabs(1, fd);
+ fprintf(fd, "*to = ltt_align(*to, sizeof(void *));\n");
+ print_tabs(1, fd);
+ fprintf(fd, "*to_base = *to_base+*to;\n");
+ print_tabs(1, fd);
+ fprintf(fd, "*to = 0;\n");
+ fprintf(fd, "\n");
+ fprintf(fd, "/* Put source *from just after the C sequence */\n");
+ print_tabs(1, fd);
+ fprintf(fd, "*from = obj+1;\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(print_type_write(type,
+ fd, 1, basename, field->name)) 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[1])->type,
+ fd, 2, basename, ((field_t*)td->fields.array[1])->name)) 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;
+}
+
+
+