changes for genevent-new types
authorcompudj <compudj@04897980-b3bd-0310-b5e0-8ef037075253>
Fri, 16 Dec 2005 18:00:29 +0000 (18:00 +0000)
committercompudj <compudj@04897980-b3bd-0310-b5e0-8ef037075253>
Fri, 16 Dec 2005 18:00:29 +0000 (18:00 +0000)
git-svn-id: http://ltt.polymtl.ca/svn@1397 04897980-b3bd-0310-b5e0-8ef037075253

ltt/branches/poly/ltt/event.c
ltt/branches/poly/ltt/facility.c
ltt/branches/poly/ltt/ltt-private.h
ltt/branches/poly/ltt/ltt.h
ltt/branches/poly/ltt/parser.c
ltt/branches/poly/ltt/parser.h
ltt/branches/poly/ltt/tracefile.c

index a5b046814027e30f74b3f9410518a85284cebdb0..53a2b2ec3c532a80adea94c3a2fb6dbb484e96fb 100644 (file)
@@ -246,23 +246,20 @@ LttEventType *ltt_event_eventtype(const LttEvent *e)
  *Function name
  *    ltt_event_field : get the root field of the event
  *Input params
- *    e               : an instance of an event type   
+ *    e               : an instance of an event type
+ *    name            : field name
  *Return value
- *    LttField *      : the root field of the event
+ *    LttField *      : The requested field, or NULL
  ****************************************************************************/
 
-LttField *ltt_event_field(LttEvent *e)
+LttField *ltt_event_field(LttEvent *e, GQuark name)
 {
   LttField * field;
   LttEventType * event_type = ltt_event_eventtype(e);
   if(unlikely(!event_type)) return NULL;
-  field = event_type->root_field;
-  if(unlikely(!field)) return NULL;
 
-  get_field_type_size(e->tracefile, event_type, 0, 0,
-      field, e->data);
+  return (LttField*)g_datalist_id_get_data(&event_type->fields_by_name, name);
   
-  return field;
 }
 
 /*****************************************************************************
@@ -448,9 +445,8 @@ guint64 ltt_event_field_element_number(LttEvent *e, LttField *f)
     return 0;
   
   if(f->field_type->type_class == LTT_ARRAY)
-    return f->field_type->element_number;
-  return ltt_get_uint(LTT_GET_BO(e->tracefile), f->sequ_number_size,
-      e + f->offset_root);
+    return f->field_type->size;
+  return ltt_get_long_unsigned(e, &g_array_index(f->fields, LttField, 0));
 }
 
 /*****************************************************************************
@@ -458,20 +454,21 @@ guint64 ltt_event_field_element_number(LttEvent *e, LttField *f)
  *    ltt_event_field_element_select
  *                   : Set the currently selected element for a sequence or
  *                     array field
- *                     O(1) if fields are of fixed size, else O(n) if fields are
- *                     of variable size.
+ *                     O(1) because of offset array.
  *Input params
  *    e              : an instance of an event type
  *    f              : a field of the instance
  *    i              : the ith element (0, ...)
+ *returns : the child field, at the right index, updated.
  ****************************************************************************/
-void ltt_event_field_element_select(LttEvent *e, LttField *f, unsigned i)
+LttField *ltt_event_field_element_select(LttEvent *e, LttField *f, gulong i)
 {
-  unsigned element_number;
+  gulong element_number;
   LttField *field;
   unsigned int k;
   size_t size;
   LttEventType *event_type;
+  off_t new_offset;
  
   if(f->field_type->type_class != LTT_ARRAY &&
      f->field_type->type_class != LTT_SEQUENCE)
@@ -482,27 +479,25 @@ void ltt_event_field_element_select(LttEvent *e, LttField *f, unsigned i)
   /* Sanity check for i : 0..n-1 only, and must be lower or equal element_number
    */
   if(i >= element_number) return;
-  
-  field = f->child[0];
-  
-  if(f->field_type->type_class == LTT_SEQUENCE)
-    size = f->sequ_number_size;
-  else
-    size = 0;
-  
-  if(field->fixed_size == FIELD_FIXED) {
-      size += field->field_size * i;
-
-      get_field_type_size(e->tracefile, event_type,
-                  f->offset_root+size, size, field, e->data);
+  if(f->field_type->type_class == LTT_ARRAY) {
+   field = &g_array_index(f->fields, LttField, 0);
+  } else {
+   field = &g_array_index(f->fields, LttField, 1);
+  }
 
+  if(field->field_size != 0) {
+    if(f->array_offset + (i * field->field_size) == field->offset_root)
+      return; /* fixed length child, already at the right offset */
+    else
+      new_offset = f->array_offset + (i * field->field_size);
   } else {
-    for(k=0;k<=i;k++){
-      size += get_field_type_size(e->tracefile, event_type,
-                  f->offset_root+size, size, field, e->data);
-    }
+    /* Var. len. child */
+    new_offset = g_array_index(f->dynamic_offsets, off_t, i);
   }
-  f->current_element = i;
+  compute_fields_offsets(e->tracefile, field, new_offset);
+
+  return field;
 }
 
 /*****************************************************************************
@@ -667,6 +662,21 @@ char *ltt_event_get_string(LttEvent *e, LttField *f)
  *    data            : a pointer to the event data.
  *Returns the field type size.
  ****************************************************************************/
+ // TODO
+// Change this function so it uses a *to offset value incrementation, just like
+// genevent-new instead of returning a size. What is of interest here is the
+// offset needed to read each field.
+//
+// Precomputed ones can be returned directly. Otherwise, the field is flagged
+// "VARIABLE OFFSET" and must be computed dynamically. The dynamic processing
+// of an offset takes the last known fixed offset, and then dynamically
+// calculates all variable field offsets from it.
+//
+// After a VARIABLE SIZE element, all fields have a variable offset.
+// Also, is an array or a sequence has variable length child, we must pass
+// through all of them, saving the offsets in the dynamic_offsets array.
+
+#if 0
 size_t get_field_type_size(LttTracefile *tf, LttEventType *event_type,
     off_t offset_root, off_t offset_parent,
     LttField *field, void *data)
@@ -674,6 +684,7 @@ size_t get_field_type_size(LttTracefile *tf, LttEventType *event_type,
   size_t size = 0;
   guint i;
   LttType *type;
+       off_t align;
   
   g_assert(field->fixed_root != FIELD_UNKNOWN);
   g_assert(field->fixed_parent != FIELD_UNKNOWN);
@@ -696,10 +707,16 @@ size_t get_field_type_size(LttTracefile *tf, LttEventType *event_type,
     case LTT_SSIZE_T:
     case LTT_OFF_T:
       g_assert(field->fixed_size == FIELD_FIXED);
-      size = field->field_size;
+                       size = field->field_size;
+      align = ltt_align(field->offset_root,
+                                                                                                                               size, event_type->facility->has_alignment);
+                       field->offset_root += align;
+                       field->offset_parent += align;
+                       size += align;
       break;
     case LTT_SEQUENCE:
       {
+                               /* FIXME : check the type of sequence identifier */
         gint seqnum = ltt_get_uint(LTT_GET_BO(tf),
                         field->sequ_number_size,
                         data + offset_root);
@@ -782,5 +799,195 @@ size_t get_field_type_size(LttTracefile *tf, LttEventType *event_type,
 
   return size;
 }
+#endif //0
+
+
+
+
+
+/*****************************************************************************
+ *Function name
+ *    compute_fields_offsets : set the precomputable offset of the fields
+ *Input params 
+ *    tf : tracefile
+ *    field : the field
+ *    offset : pointer to the current offset, must be incremented
+ ****************************************************************************/
+
+
+void compute_fields_offsets(LttTracefile *tf, LttField *field, off_t *offset,
+    void *root)
+{
+  type = &field->field_type;
+
+  switch(type->type_class) {
+    case LTT_INT_FIXED:
+    case LTT_UINT_FIXED:
+    case LTT_POINTER:
+    case LTT_CHAR:
+    case LTT_UCHAR:
+    case LTT_SHORT:
+    case LTT_USHORT:
+    case LTT_INT:
+    case LTT_UINT:
+    case LTT_LONG:
+    case LTT_ULONG:
+    case LTT_SIZE_T:
+    case LTT_SSIZE_T:
+    case LTT_OFF_T:
+    case LTT_FLOAT:
+    case LTT_ENUM:
+      if(field->fixed_root == FIELD_VARIABLE) {
+        /* Align offset on type size */
+        *offset += ltt_align(*offset, get_alignment(tf, field),
+                             tf->has_alignment);
+        /* remember offset */
+        field->offset_root = *offset;
+        /* Increment offset */
+        *offset += field->field_size;
+      }
+      /* None of these types has variable size, so we are sure that if
+       * this element has a fixed_root, then the following one will have
+       * a fixed root too, so it does not need the *offset at all.
+       */
+      break;
+    case LTT_STRING:
+      if(field->fixed_root == FIELD_VARIABLE) {
+        field->offset_root = *offset;
+      }
+      *offset += strlen((gchar*)(root+*offset)) + 1;
+      break;
+    case LTT_ARRAY:
+      g_assert(type->fields->len == 1);
+      {
+        off_t local_offset;
+        LttField *child = &g_array_index(type->fields, LttField, 0);
+        if(field->fixed_root == FIELD_VARIABLE) {
+          *offset += ltt_align(*offset, get_alignment(tf, field),
+                              tf->has_alignment);
+          /* remember offset */
+          field->offset_root = *offset;
+          field->array_offset = *offset;
+        }
+     
+        if(field->field_size != 0) {
+          /* Increment offset */
+          /* field_size is the array size in bytes */
+          *offset = field->offset_root + field->field_size;
+        } else {
+          guint i;
+          *offset = field->array_offset;
+          field->dynamic_offsets = g_array_set_size(field->dynamic_offsets,
+                                                    0);
+          for(i=0; i<type->size; i++) {
+            g_array_append_val(field->dynamic_offsets, *offset);
+            compute_fields_offsets(tf, child, offset);
+          }
+        }
+  //      local_offset = field->array_offset;
+  //      /* Set the offset at position 0 */
+  //      compute_fields_offsets(tf, child, &local_offset);
+        break;
+    case LTT_SEQUENCE:
+      g_assert(type->fields->len == 2);
+      {
+        off_t local_offset;
+        LttField *child;
+        guint i;
+        if(field->fixed_root == FIELD_VARIABLE) {
+          *offset += ltt_align(*offset, get_alignment(tf, field),
+                              tf->has_alignment);
+          /* remember offset */
+          field->offset_root = *offset;
+
+          child = &g_array_index(type->fields, LttField, 0);
+          compute_fields_offsets(tf, child, offset);
+          child = &g_array_index(type->fields, LttField, 1);
+          *offset += ltt_align(*offset, get_alignment(tf, child),
+                               tf->has_alignment);
+          field->array_offset = *offset;
+
+        } else {
+          child = &g_array_index(type->fields, LttField, 1);
+        }
+        *offset = field->array_offset;
+        field->dynamic_offsets = g_array_set_size(field->dynamic_offsets,
+                                                  0);
+        for(i=0; i<ltt_event_field_element_number(&tf->event, field); i++) {
+          g_array_append_val(field->dynamic_offsets, *offset);
+          compute_fields_offsets(tf, child, offset);
+        }
+ //       local_offset = field->array_offset;
+ //       /* Set the offset at position 0 */
+ //       compute_fields_offsets(tf, child, &local_offset);
+      }
+      break;
+    case LTT_STRUCT:
+      { 
+        LttField *child;
+        guint i;
+        gint ret=0;
+        if(field->fixed_root == FIELD_VARIABLE) {
+          *offset += ltt_align(*offset, get_alignment(tf, field),
+                               tf->has_alignment);
+          /* remember offset */
+          field->offset_root = *offset;
+        } else {
+          *offset = field->offset_root;
+        }
+        for(i=0; i<type->fields->len; i++) {
+          child = &g_array_index(type->fields, LttField, i);
+          compute_fields_offsets(tf, child, offset);
+        }
+      }
+      break;
+    case LTT_UNION:
+      { 
+        LttField *child;
+        guint i;
+        gint ret=0;
+        if(field->fixed_root == FIELD_VARIABLE) {
+          *offset += ltt_align(*offset, get_alignment(tf, field),
+                               tf->has_alignment);
+          /* remember offset */
+          field->offset_root = *offset;
+        }
+        for(i=0; i<type->fields->len; i++) {
+          *offset = field->offset_root;
+          child = &g_array_index(type->fields, LttField, i);
+          compute_fields_offsets(tf, child, offset);
+        }
+        *offset = field->offset_root + field->field_size;
+      }
+      break;
+    case LTT_NONE:
+    default:
+      g_error("compute_fields_offsets : unknown type");
+  }
+
+}
 
 
+/*****************************************************************************
+ *Function name
+ *    compute_offsets : set the dynamically computable offsets of an event type
+ *Input params 
+ *    tf : tracefile
+ *    event : event type
+ *
+ ****************************************************************************/
+void compute_offsets(LttTracefile *tf, LttEventType *event, size_t *offset,
+      void *root)
+{
+  guint i;
+  gint ret;
+
+  /* compute all variable offsets */
+  for(i=0; i<event->fields->len; i++) {
+    LttField *field = &g_array_index(event->fields, LttField, i);
+    ret = compute_fields_offsets(tf, field, offset, root);
+    if(ret) break;
+  }
+
+}
+
index f4c0acae6c939f6f488a31cbc6c9fd40d908c1fd..75b89bed5e01f1a084d2b6d2e7e324bcba1f3cd3 100644 (file)
@@ -171,11 +171,9 @@ void generateFacility(LttFacility *f, facility_t *fac, guint32 checksum)
 {
   char * facilityName = fac->name;
   sequence_t * events = &fac->events;
-  int i;
-  //LttEventType * evType;
-  LttEventType * event_type;
-  LttField * field;
+  unsigned int i, j;
   LttType * type;
+  table_t *named_types = &fac->named_types;
   
   g_assert(f->name == g_quark_from_string(facilityName));
   g_assert(f->checksum == checksum);
@@ -190,56 +188,67 @@ void generateFacility(LttFacility *f, facility_t *fac, guint32 checksum)
 
   g_datalist_init(&f->events_by_name);
   g_datalist_init(&f->named_types);
-  
-  //f->named_types_number = fac->named_types.keys.position;
-  //f->named_types = g_array_sized_new (FALSE, TRUE, sizeof(LttType),
-  //    fac->named_types.keys.position);
-  //f->named_types = g_new(LttType*, fac->named_types.keys.position);
-  //f->named_types = g_array_set_size(f->named_types, 
-  //    fac->named_types.keys.position);
-
-  //for each event, construct field tree and type graph
+#if 0
+  /* The first day, he created the named types */
+
+  for(i=0; i<named_types->keys.position; i++) {
+    GQuark name = g_quark_from_string((char*)named_types->keys.array[i]);
+    type_descriptor_t *td = (type_descriptor_t*)named_types->values.array[i];
+
+    /* Create the type */
+    type = g_new(LttType,1);
+    type->type_name = name;
+    type->type_class = td->type;
+    if(td->fmt) type->fmt = g_strdup(td->fmt);
+    else type->fmt = NULL;
+    type->size = td->size;
+    type->enum_strings = NULL;
+    type->element_type = NULL;
+    type->element_number = 0;
+
+    construct_types_and_fields(type, td, NULL, NULL, ...);
+    
+    g_datalist_id_set_data_full(&fac->named_types, name,
+                type, (GDestroyNotify)freeLttNamedType);
+
+  }
+#endif //0
+  /* The second day, he created the event fields and types */
+  //for each event, construct field and type acyclic graph
   for(i=0;i<events->position;i++){
-    event_type = &g_array_index(f->events, LttEventType, i);
-    //evType = g_new(LttEventType,1);
-    //f->events[i] = evType;
+               event_t parser_event = (event_t*)events->array[i];
+    LttEventType *event_type = &g_array_index(f->events, LttEventType, i);
 
     event_type->name = 
-      g_quark_from_string(((event_t*)(events->array[i]))->name);
+      g_quark_from_string(parser_event->name);
     
     g_datalist_id_set_data(&f->events_by_name, event_type->name,
         event_type);
     
     event_type->description =
-      g_strdup(((event_t*)(events->array[i]))->description);
+      g_strdup(parser_event->description);
     
-    field = g_new(LttField, 1);
-    event_type->root_field = field;
-    event_type->facility = f;
     event_type->index = i;
+    event_type->facility = f;
 
-    if(((event_t*)(events->array[i]))->type != NULL){
- //     field->field_pos = 0;
-      type = lookup_named_type(f,((event_t*)(events->array[i]))->type);
-      field->field_type = type;
-      field->offset_root = 0;
-      field->fixed_root = FIELD_UNKNOWN;
-      field->offset_parent = 0;
-      field->fixed_parent = FIELD_UNKNOWN;
-      //    field->base_address = NULL;
-      field->field_size  = 0;
-      field->fixed_size = FIELD_UNKNOWN;
-      field->parent = NULL;
-      field->child = NULL;
-      field->current_element = 0;
-
-      //construct field tree and type graph
-      construct_types_and_fields(f,((event_t*)(events->array[i]))->type,field);
-    }else{
-      event_type->root_field = NULL;
-      g_free(field);
+    event_type->fields = g_array_sized_new(FALSE, TRUE,
+        sizeof(LttField), parser_event->fields.position);
+    event_type->fields = 
+      g_array_set_size(event_type->fields, parser_event->fields.position);
+    g_datalist_init(&event_type->fields_by_name);
+  
+    for(j=0; j<parser_event->fields.position; j++) {
+      LttField *field = &g_array_index(event_type->fields, LttField, j);
+      field_t *parser_field = (field_t*)parser_event->fields.array[j];
+
+      construct_types_and_fields(NULL, NULL, field, parser_field, ...);
+      g_datalist_id_set_data(&event_type->fields_by_name, 
+         field->name, 
+         field);
     }
-  }  
+  }
+
+  /* What about 2 days weeks ? */
 }
 
 
@@ -249,11 +258,219 @@ void generateFacility(LttFacility *f, facility_t *fac, guint32 checksum)
  *                             internal recursion function
  *Input params 
  *    fac                    : facility struct
- *    td                     : type descriptor
- *    root_field             : root field of the event
+ *    field                  : destination lttv field
+ *    fld                    : source parser field
  ****************************************************************************/
 
+//DONE
+//make the change for arrays and sequences
+//no more root field. -> change this for an array of fields.
+// Compute the field size here.
+// Flag fields as "VARIABLE OFFSET" or "FIXED OFFSET" : as soon as
+// a field with a variable size is found, all the following fields must
+// be flagged with "VARIABLE OFFSET", this will be done by the offset
+// precomputation.
+
 
+void construct_fields(LttFacility *fac,
+                                                                                       LttField *field,
+                      field_t *fld)
+{
+  guint len;
+  type_descriptor_t *td;
+
+  field->name = g_quark_from_string(fld->name);
+  if(fld->description) {
+    len = strlen(fld->description);
+    field->description = g_new(gchar, len+1);
+    strcpy(field->description, fld->description);
+  }
+  field->dynamic_offsets = NULL;
+  type = &field->field_type;
+  td = fld->type;
+
+  type->enum_map = NULL;
+  type->fields = NULL;
+  type->fields_by_name = NULL;
+  switch(td->type) {
+    case INT_FIXED:
+      type->type_class = LTT_INT_FIXED;
+      type->size = td->size;
+      break;
+    case UINT_FIXED:
+      type->type_class = LTT_UINT_FIXED;
+      type->size = td->size;
+      break;
+    case POINTER:
+      type->type_class = LTT_POINTER;
+      type->size = fac->pointer_size;
+      break;
+    case CHAR:
+      type->type_class = LTT_CHAR;
+      type->size = td->size;
+      break;
+    case UCHAR:
+      type->type_class = LTT_UCHAR;
+      type->size = td->size;
+      break;
+    case SHORT:
+      type->type_class = LTT_SHORT;
+      type->size = td->size;
+      break;
+    case USHORT:
+      type->type_class = LTT_USHORT;
+      type->size = td->size;
+      break;
+    case INT:
+      type->type_class = LTT_INT;
+      type->size = fac->int_size;
+      break;
+    case UINT:
+      type->type_class = LTT_UINT;
+      type->size = fac->int_size;
+      break;
+    case LONG:
+      type->type_class = LTT_LONG;
+      type->size = fac->long_size;
+      break;
+    case ULONG:
+      type->type_class = LTT_ULONG;
+      type->size = fac->long_size;
+      break;
+    case SIZE_T:
+      type->type_class = LTT_SIZE_T;
+      type->size = fac->size_t_size;
+      break;
+    case SSIZE_T:
+      type->type_class = LTT_SSIZE_T;
+      type->size = fac->size_t_size;
+      break;
+    case OFF_T:
+      type->type_class = LTT_OFF_T;
+      type->size = fac->size_t_size;
+      break;
+    case FLOAT:
+      type->type_class = LTT_FLOAT;
+      type->size = td->size;
+      break;
+    case STRING:
+      type->type_class = LTT_STRING;
+      type->size = 0;
+      break;
+    case ENUM:
+      type->type_class = LTT_ENUM;
+      type->size = fac->int_size;
+      {
+        guint i;
+        g_datalist_init(&type->enum_map);
+        for(i=0; i<td->labels.position; i++) {
+          GQuark key = g_quark_from_string((char*)td->labels.array[i]);
+          int *src = (int*)td->labels_values.array[i];
+          /* it's always ok to cast a int to a pointer type */
+          g_datalist_id_set_data(&type->enum_map, key, (gpointer)*src);
+        }
+      }
+      break;
+    case ARRAY:
+      type->type_class = LTT_ARRAY;
+      type->size = td->size;
+      type->fields = g_array_sized_new(FALSE, TRUE, sizeof(LttField),
+          td->fields.position);
+      type->fields = g_array_set_size(type->fields, td->fields.position);
+      {
+        guint i;
+
+        for(i=0; i<td->fields.position; i++) {
+          field_t *schild = (field_t*)td->fields.array[i];
+          LttField *dchild = &g_array_index(type->fields, LttField, i);
+          
+          construct_fields(fac, dchild, schild);
+        }
+      }
+      break;
+    case SEQUENCE:
+      type->type_class = LTT_SEQUENCE;
+      type->size = 0;
+      type->fields = g_array_sized_new(FALSE, TRUE, sizeof(LttField),
+          td->fields.position);
+      type->fields = g_array_set_size(type->fields, td->fields.position);
+      {
+        guint i;
+
+        for(i=0; i<td->fields.position; i++) {
+          field_t *schild = (field_t*)td->fields.array[i];
+          LttField *dchild = &g_array_index(type->fields, LttField, i);
+          
+          construct_fields(fac, dchild, schild);
+        }
+      }
+      break;
+    case STRUCT:
+      type->type_class = LTT_STRUCT;
+      type->size = 0; // Size not calculated by the parser.
+      type->fields = g_array_sized_new(FALSE, TRUE, sizeof(LttField),
+          td->fields.position);
+      type->fields = g_array_set_size(type->fields, td->fields.position);
+      g_datalist_init(&type->fields_by_name);
+      {
+        guint i;
+
+        for(i=0; i<td->fields.position; i++) {
+          field_t *schild = (field_t*)td->fields.array[i];
+          LttField *dchild = &g_array_index(type->fields, LttField, i);
+          
+          construct_fields(fac, dchild, schild);
+          g_datalist_id_set_data(&type->fields_by_name, 
+             dchild->name, 
+             dchild);
+        }
+      }
+      break;
+    case UNION:
+      type->type_class = LTT_UNION;
+      type->size = 0; // Size not calculated by the parser.
+      type->fields = g_array_sized_new(FALSE, TRUE, sizeof(LttField),
+          td->fields.position);
+      type->fields = g_array_set_size(type->fields, td->fields.position);
+      g_datalist_init(&type->fields_by_name);
+      {
+        guint i;
+
+        for(i=0; i<td->fields.position; i++) {
+          field_t *schild = (field_t*)td->fields.array[i];
+          LttField *dchild = &g_array_index(type->fields, LttField, i);
+          
+          construct_fields(fac, dchild, schild);
+          g_datalist_id_set_data(&type->fields_by_name, 
+             dchild->name, 
+             dchild);
+        }
+      }
+      break;
+    case NONE:
+    default:
+      g_error("construct_fields : unknown type");
+  }
+
+  field->field_size = type->size;
+
+  /* Put the fields as "variable" offset to root first. Then,
+   * the offset precomputation will only have to set the FIELD_FIXED until
+   * it reaches the first variable length field, then stop.
+   */
+  field->fixed_root = FIELD_VARIABLE;
+
+  if(td->fmt) {
+    len = strlen(td->fmt);
+    type->fmt = g_new(gchar, len+1);
+    strcpy(type->fmt, td->fmt);
+  }
+}
+
+
+
+#if 0
 void construct_types_and_fields(LttFacility * fac, type_descriptor_t * td, 
                             LttField * fld)
 {
@@ -349,7 +566,7 @@ void construct_types_and_fields(LttFacility * fac, type_descriptor_t * td,
 
 }
 
-
+#endif //0
 
 #if 0
 void construct_types_and_fields(LttFacility * fac, type_descriptor * td, 
@@ -433,29 +650,27 @@ void construct_types_and_fields(LttFacility * fac, type_descriptor * td,
 }
 #endif //0
 
+#if 0
 /*****************************************************************************
  *Function name
  *    lookup_named_type: search named type in the table
  *                       internal function
  *Input params 
  *    fac              : facility struct
- *    td               : type descriptor
+ *    name             : type name
  *Return value    
  *                     : either find the named type, or create a new LttType
  ****************************************************************************/
 
-LttType * lookup_named_type(LttFacility *fac, type_descriptor_t * td)
+LttType * lookup_named_type(LttFacility *fac, GQuark type_name)
 {
   LttType *type = NULL;
-  GQuark name = 0;
-  
-  if(td->type_name != NULL) {
-    /* Named type */
-    name = g_quark_from_string(td->type_name);
-  
-    type = g_datalist_id_get_data(&fac->named_types, name);
-  }
   
+  /* Named type */
+  type = g_datalist_id_get_data(&fac->named_types, name);
+
+  g_assert(type != NULL);
+#if 0
   if(type == NULL){
     /* Create the type */
     type = g_new(LttType,1);
@@ -472,9 +687,10 @@ LttType * lookup_named_type(LttFacility *fac, type_descriptor_t * td)
       g_datalist_id_set_data_full(&fac->named_types, name,
                   type, (GDestroyNotify)freeLttNamedType);
   }
+#endif //0
   return type;
 }
-
+#endif //0
 
 /*****************************************************************************
  *Function name
@@ -505,71 +721,63 @@ void freeFacility(LttFacility * fac)
   }
   g_array_free(fac->events, TRUE);
 
-  g_datalist_clear(&fac->named_types);
+  g_datalist_clear(&fac->events_by_name);
 
+ // g_datalist_clear(&fac->named_types);
 }
 
 void freeEventtype(LttEventType * evType)
 {
+  unsigned int i;
   LttType * root_type;
   if(evType->description)
-    g_free(evType->description); 
-  if(evType->root_field){    
-    root_type = evType->root_field->field_type;
-    freeLttField(evType->root_field);
-    freeLttType(&root_type);
+    g_free(evType->description);
+  
+  for(i=0; i<evType->fields->len;i++) {
+    freeLttType(&g_array_index(evType->fields, LttType, i));
   }
+  g_array_free(evType->fields, TRUE);
+  g_datalist_clear(&evType->fields_by_name);
+}
+
+void freeLttType(LttType * type)
+{
+  unsigned int i;
+
+  if(type->fmt)
+    g_free(type->fmt);
+
+  if(type->enum_map)
+    g_datalist_clear(&type->enum_map);
+
+  if(type->fields) {
+    for(i=0; i<type->fields->len; i++) {
+      freeLttField(&g_array_index(type->fields, LttField, i));
+    }
+    g_array_free(type->fields, TRUE);
+  }
+  if(type->fields_by_name)
+    g_datalist_clear(&type->fields_by_name);
 }
 
 void freeLttNamedType(LttType * type)
 {
-  freeLttType(&type);
+  freeLttType(type);
 }
 
-void freeLttType(LttType ** type)
+void copy_enum_element(GQuark keyid, gpointer data, gpointer user_data)
 {
-  unsigned int i;
-  if(*type == NULL) return;
-  if((*type)->type_name != 0) return; //this is a named type.
-  //if((*type)->type_name){
-  //  return; //this is a named type
-  //}
-  if((*type)->fmt)
-    g_free((*type)->fmt);
-  if((*type)->enum_strings){
-    g_free((*type)->enum_strings);
-  }
+  int *value = gpointer data;
 
-  if((*type)->element_type){
-    for(i=0;i<(*type)->element_number;i++)
-      freeLttType(&((*type)->element_type[i]));   
-    g_free((*type)->element_type);
-  }
-  g_free(*type);
-  *type = NULL;
 }
 
-void freeLttField(LttField * fld)
+void freeLttField(LttField * field)
 { 
-  int i;
-  int size = 0;
-  
-  if(fld->field_type){
-    if(fld->field_type->type_class == LTT_ARRAY ||
-       fld->field_type->type_class == LTT_SEQUENCE){
-      size = 1;
-    }else if(fld->field_type->type_class == LTT_STRUCT){
-      size = fld->field_type->element_number;
-    }
-  }
-
-  if(fld->child){
-    for(i=0; i<size; i++){
-      if(fld->child[i])freeLttField(fld->child[i]);
-    }
-    g_free(fld->child);
-  }
-  g_free(fld);
+  if(field->description)
+    g_free(field->description);
+  if(field->dynamic_offsets)
+    g_array_free(field->dynamic_offsets, TRUE);
+  freeLttType(field->type);
 }
 
 /*****************************************************************************
index 666f1f338b82d974cf4474828044adb6e9986f49..03da264e64cd64e97ccbf21ca7c893972b816ce7 100644 (file)
@@ -47,6 +47,8 @@
 #define LTT_GET_FLOAT_BO(t) \
   (((t)->float_word_order==__BYTE_ORDER)?0:1)
 
+#define SEQUENCE_AVG_ELEMENTS 1000
+                               
 /* Hardcoded core events */
 enum ltt_core_events {
     LTT_EVENT_FACILITY_LOAD,
@@ -98,10 +100,11 @@ typedef guint64 uint64_t;
 struct LttFacilityLoad {
   guint32 checksum;
   guint32 id;
+       guint32 int_size;
   guint32 long_size;
   guint32 pointer_size;
   guint32 size_t_size;
-  guint32 alignment;
+       guint32 has_alignment;
 } LTT_PACKED_STRUCT;
 
 struct LttFacilityUnload {
@@ -111,10 +114,11 @@ struct LttFacilityUnload {
 struct LttStateDumpFacilityLoad {
   guint32 checksum;
   guint32 id;
+       guint32 int_size;
   guint32 long_size;
   guint32 pointer_size;
   guint32 size_t_size;
-  guint32 alignment;
+       guint32 has_alignment;
 } LTT_PACKED_STRUCT;
 
 typedef struct _TimeHeartbeat {
@@ -187,7 +191,7 @@ struct ltt_trace_header_0_4 {
   uint64_t        start_freq;
   uint64_t        start_tsc;
   uint64_t        start_monotonic;
-  struct timespec start_time;
+  struct timeval       start_time;
 } LTT_PACKED_STRUCT;
 
 
@@ -209,23 +213,23 @@ struct ltt_block_start_header {
 
 
 struct _LttType{
-  GQuark type_name;                //type name if it is a named type
-  GQuark element_name;             //elements name of the struct
+// LTTV does not care about type names. Everything is a field.
+// GQuark type_name;                //type name if it is a named type
   gchar * fmt;
-  unsigned int size;
+  guint size;
   LttTypeEnum type_class;          //which type
-  GQuark * enum_strings;            //for enum labels
-  struct _LttType ** element_type; //for array, sequence and struct
-  unsigned element_number;         //the number of elements 
-                                   //for enum, array, sequence and structure
+  GData *enum_map;                 //maps enum labels to numbers.
+  GArray *fields;     // Array of LttFields, for array, sequence, union, struct.
+  GData *fields_by_name;
 };
 
 struct _LttEventType{
   GQuark name;
   gchar * description;
-  guint index;              //id of the event type within the facility
+  guint index;            //id of the event type within the facility
   LttFacility * facility; //the facility that contains the event type
-  LttField * root_field;  //root field
+  GArray * fields;        //event's fields (LttField)
+  GData *fields_by_name;
 };
 
 /* Structure LttEvent and LttEventPosition must begin with the _exact_ same
@@ -274,65 +278,41 @@ struct _LttEventPosition{
 enum field_status { FIELD_UNKNOWN, FIELD_VARIABLE, FIELD_FIXED };
 
 struct _LttField{
-  //guint field_pos;           //field position within its parent
-  LttType * field_type;      //field type, if it is root field
-                             //then it must be struct type
-
-  off_t offset_root;         //offset from the root, -1:uninitialized 
-  enum field_status fixed_root;          //offset fixed according to the root
-                             //-1:uninitialized, 0:unfixed, 1:fixed
-  off_t offset_parent;       //offset from the parent,-1:uninitialized
-  enum field_status fixed_parent;        //offset fixed according to its parent
-                             //-1:uninitialized, 0:unfixed, 1:fixed
-  //  void * base_address;       //base address of the field  ????
-  
-  guint field_size;     //      //>0: size of the field, 
-                          //   //0 : uncertain
-                           //  //-1: uninitialize
-  enum field_status fixed_size;
-
-  /* for sequence */
-  gint sequ_number_size;      //the size of unsigned used to save the
-                             //number of elements in the sequence
-
-  gint element_size;          //the element size of the sequence
-  //int field_fixed;           //0: field has string or sequence
-                             //1: field has no string or sequenc
-                             //-1: uninitialize
-
-  struct _LttField * parent;
-  struct _LttField ** child; //for array, sequence, struct and union: 
-                             //list of fields, it may have only one
-                             //field if the element is not a struct or
-                             //union
-  unsigned current_element;  //which element is currently processed
-                             // Used for sequences and arrays.
+  GQuark name;
+  gchar *description;
+  LttType field_type;      //field type
+
+  off_t offset_root;            //offset from the root
+  enum field_status fixed_root; //offset fixed according to the root
+
+  guint field_size;       // size of the field
+                          // Only if field type size is set to 0
+                          // (it's variable), then the field_size should be
+                          // dynamically calculated while reading the trace
+                          // and put here. Otherwise, the field_size always
+                          // equels the type size.
+  off_t array_offset;     // offset of the beginning of the array (for array
+                          // and sequences)
+  GArray * dynamic_offsets; // array of offsets calculated dynamically at
+                            // each event for sequences and arrays that
+                            // contain variable length fields.
 };
 
-
 struct _LttFacility{
   LttTrace  *trace;
-  //gchar * name;               //facility name 
   GQuark name;
   guint32 checksum;      //checksum of the facility 
   guint32  id;          //id of the facility
  
-  guint32 pointer_size;
+  guint32 int_size;
   guint32 long_size;
+  guint32 pointer_size;
   guint32 size_t_size;
   guint32 alignment;
 
-
-  //LttEventType ** events;    //array of event types 
-  //unsigned int event_number;          //number of events in the facility 
-  //LttType ** named_types;
-  //unsigned int named_types_number;
-
   GArray *events;
   GData *events_by_name;
- // GArray *named_types;
-  //GData *named_types_by_name;
-  GData *named_types;
+ // not necessary in LTTV GData *named_types;
   
   unsigned char exists; /* 0 does not exist, 1 exists */
 };
@@ -369,9 +349,11 @@ struct _LttTracefile{
   int fd;                            //file descriptor 
   off_t file_size;                   //file size
   //unsigned block_size;               //block_size
-  unsigned int num_blocks;           //number of blocks in the file
+  guint num_blocks;           //number of blocks in the file
   gboolean  reverse_bo;              //must we reverse byte order ?
   gboolean  float_word_order;        //what is the byte order of floats ?
+       size_t          has_alignment;                                   //alignment of events in the tracefile.
+                                                                                                                                                // 0 or the architecture size in bytes.
 
   size_t    buffer_header_size;
 
@@ -412,7 +394,6 @@ struct _LttTrace{
   guint8    ltt_minor_version;
   guint8    flight_recorder;
   guint8    has_heartbeat;
-  guint8    has_alignment;
        guint8          has_tsc;
   uint64_t  start_freq;
   uint64_t  start_tsc;
@@ -454,4 +435,21 @@ struct _LttSystemDescription {
 //#define EVENT_HEADER_SIZE (TIMESTAMP_SIZE + EVENT_ID_SIZE)
 
 
+/* Calculate the offset needed to align the type.
+ * If has_alignment is 0, alignment is disactivated.
+ * else, the function returns the offset needed to
+ * align align_drift on the has_alignment value (should be
+ * the size of the architecture). */
+static inline unsigned int ltt_align(size_t align_drift,
+                                                                                                                                                size_t size_of_type,
+                                                                                                                                                size_t has_alignment)
+{
+       size_t alignment = min(has_alignment, size_of_type);
+
+       return ((alignment - align_drift) & (alignment-1));
+}
+
+off_t field_align(LttTracefile *tf, LttField *field, off_t offset);
+
+
 #endif /* LTT_PRIVATE_H */
index 02d937c24b003f787560ffdab2b0f57f2a8fe2d9..e0c7a731e0ed1d4a20f46fe88afecba004d52d8e 100644 (file)
@@ -1,5 +1,6 @@
 /* This file is part of the Linux Trace Toolkit trace reading library
  * Copyright (C) 2003-2004 Michel Dagenais
+ *               2005 Mathieu Desnoyers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -131,10 +132,28 @@ typedef enum _LttArchEndian
 } LttArchEndian;
 
 typedef enum _LttTypeEnum 
-{ LTT_INT, LTT_UINT, LTT_POINTER, LTT_LONG, LTT_ULONG, LTT_SIZE_T, 
-  LTT_SSIZE_T, LTT_OFF_T, LTT_FLOAT, LTT_STRING, LTT_ENUM, LTT_ARRAY, 
-  LTT_SEQUENCE, LTT_STRUCT, LTT_UNION
+{ LTT_INT_FIXED,
+  LTT_UINT_FIXED,
+  LTT_POINTER,
+  LTT_CHAR,
+  LTT_UCHAR,
+  LTT_SHORT,
+  LTT_USHORT,
+  LTT_INT,
+  LTT_UINT,
+  LTT_LONG,
+  LTT_ULONG,
+  LTT_SIZE_T,
+  LTT_SSIZE_T,
+  LTT_OFF_T,
+  LTT_FLOAT,
+  LTT_STRING,
+  LTT_ENUM,
+  LTT_ARRAY,
+  LTT_SEQUENCE,
+  LTT_STRUCT,
+  LTT_UNION,
+  LTT_NONE
 } LttTypeEnum;
-
-
+  
 #endif // LTT_H
index 795b3f96f4ba0d5a8be7be6ab666c293c5b2c16b..2316299249c680dd4acaa9c13faf14261469785d 100644 (file)
@@ -3,14 +3,15 @@
 parser.c: Generate helper declarations and functions to trace events
   from an event description file.
 
-Copyright (C) 2002, Xianxiu Yang
-Copyright (C) 2002, Michel Dagenais 
-This program is free software; you can redistribute it and/or modify
+           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.
+   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
+   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.
 
@@ -43,15 +44,14 @@ This program is distributed in the hope that it will be useful,
 #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" };
 
 
 
@@ -68,7 +68,7 @@ void strupper(char *string)
 }
 
 
-int getSizeindex(int value)
+int getSizeindex(unsigned int value)
 { 
   switch(value) {
     case 1:
@@ -94,21 +94,13 @@ int getSizeindex(int value)
  *    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;
@@ -183,13 +175,13 @@ char *allocAndCopy(char *str)
  *
  **************************************************************************/
 
-void getTypeAttributes(parse_file_t *in, type_descriptor_t *t)
+void getTypeAttributes(parse_file_t *in, type_descriptor_t *t,
+                          sequence_t * unnamed_types, table_t * named_types) 
 {
   char * token;
 
   t->fmt = NULL;
-  t->size = -1;
-  t->alignment = 0;
+  t->size = 0;
   
   while(1) {
     token = getToken(in); 
@@ -210,9 +202,6 @@ void getTypeAttributes(parse_file_t *in, type_descriptor_t *t)
     } else if(!strcmp("size",token)) {
       getEqual(in);
       t->size = getSize(in);
-    } else if(!strcmp("align",token)) {
-      getEqual(in);
-      t->alignment = getNumber(in);
     }
   }
 }
@@ -477,36 +466,62 @@ void parseEvent(parse_file_t *in, event_t * ev, sequence_t * unnamed_types,
                table_t * named_types) 
 {
   char *token;
+       field_t *f;
 
+       sequence_init(&(ev->fields));
   //<event name=eventtype_name>
   getEventAttributes(in, ev);
   if(ev->name == NULL) in->error(in, "Event not named");
   getRAnglebracket(in);  
 
-  //<description>...</descriptio>
+  //<description>...</description>
   ev->description = getDescription(in); 
   
-  //event can have STRUCT, TYPEREF or NOTHING
-  getLAnglebracket(in);
-
-  token = getToken(in);
-  if(in->type == FORWARDSLASH){ //</event> NOTHING
-    ev->type = NULL;
-  }else if(in->type == NAME){
-    if(strcmp("struct",token)==0 || strcmp("typeref",token)==0){
-      ungetToken(in);
-      ev->type = parseType(in,NULL, unnamed_types, named_types);
-      if(ev->type->type != STRUCT && ev->type->type != NONE) 
-       in->error(in,"type must be a struct");     
-    }else in->error(in, "not a valid type");
-
-    getLAnglebracket(in);
-    getForwardslash(in);    
-  }else in->error(in,"not a struct type");
-
-  token = getName(in);
-  if(strcmp("event",token))in->error(in,"not an event definition");
-  getRAnglebracket(in);  //</event>
+       int got_end = 0;
+       /* Events can have multiple fields. each field form at least a function
+        * parameter of the logging function. */
+       while(!got_end) {
+               getLAnglebracket(in);
+               token = getToken(in);
+               
+               switch(in->type) {
+               case FORWARDSLASH:      /* </event> */
+                       token = getName(in);
+                       if(strcmp("event",token))in->error(in,"not an event definition");
+                       getRAnglebracket(in);  //</event>
+                       got_end = 1;
+                       break;
+               case NAME: /* a field */
+                       if(strcmp("field",token))in->error(in,"expecting a field");
+                       f = (field_t *)memAlloc(sizeof(field_t));
+                       sequence_push(&(ev->fields),f);
+                       parseFields(in, f, unnamed_types, named_types, 1);
+                       break;
+               default:
+                       in->error(in, "expecting </event> or <field >");
+                       break;
+               }
+       }
+#if 0
+               if(in->type == FORWARDSLASH){ //</event> NOTHING
+                       ev->type = NULL;
+               }else if(in->type == NAME){
+                       if(strcmp("struct",token)==0 || strcmp("typeref",token)==0){
+                               ungetToken(in);
+                               ev->type = parseType(in,NULL, unnamed_types, named_types);
+                               if(ev->type->type != STRUCT && ev->type->type != NONE) 
+               in->error(in,"type must be a struct");     
+                       }else in->error(in, "not a valid type");
+
+                       getLAnglebracket(in);
+                       getForwardslash(in);    
+               }else in->error(in,"not a struct type");
+               getLAnglebracket(in);
+               getForwardslash(in);    
+               token = getName(in);
+               if(strcmp("event",token))in->error(in,"not an event definition");
+               getRAnglebracket(in);  //</event>
+#endif //0
 }
 
 /*****************************************************************************
@@ -514,37 +529,38 @@ void parseEvent(parse_file_t *in, event_t * ev, sequence_t * unnamed_types,
  *    parseField    : get field infomation from buffer 
  *Input params 
  *    in            : input file handle
- *    t             : type descriptor
+ *    f             : field
  *    unnamed_types : array of unamed types
  *    named_types   : array of named types
+ *    tag                                              : is field surrounded by a <field> </field> tag ?
  ****************************************************************************/
 
-void parseFields(parse_file_t *in, type_descriptor_t *t,
+void parseFields(parse_file_t *in, field_t *f,
     sequence_t * unnamed_types,
-               table_t * named_types) 
+               table_t * named_types,
+               int tag) 
 {
   char * token;
-  field_t *f;
-
-  f = (field_t *)memAlloc(sizeof(field_t));
-  sequence_push(&(t->fields),f);
-
-  //<field name=field_name> <description> <type> </field>
-  getFieldAttributes(in, f);
-  if(f->name == NULL) in->error(in, "Field not named");
-  getRAnglebracket(in);
+       if(tag) {
+               //<field name=field_name> <description> <type> </field>
+               getFieldAttributes(in, f);
+               if(f->name == NULL) in->error(in, "Field not named");
+               getRAnglebracket(in);
 
-  f->description = getDescription(in);
+               f->description = getDescription(in);
+       }
 
   //<int size=...>
   getLAnglebracket(in);
   f->type = parseType(in,NULL, unnamed_types, named_types);
 
-  getLAnglebracket(in);
-  getForwardslash(in);
-  token = getName(in);
-  if(strcmp("field",token))in->error(in,"not a valid field definition");
-  getRAnglebracket(in); //</field>
+       if(tag) {
+               getLAnglebracket(in);
+               getForwardslash(in);
+               token = getName(in);
+               if(strcmp("field",token))in->error(in,"not a valid field definition");
+               getRAnglebracket(in); //</field>
+       }
 }
 
 
@@ -573,6 +589,7 @@ type_descriptor_t *parseType(parse_file_t *in, type_descriptor_t *inType,
 {
   char *token;
   type_descriptor_t *t;
+       field_t *f;
 
   if(inType == NULL) {
     t = (type_descriptor_t *) memAlloc(sizeof(type_descriptor_t));
@@ -587,13 +604,16 @@ type_descriptor_t *parseType(parse_file_t *in, type_descriptor_t *inType,
 
   if(strcmp(token,"struct") == 0) {
     t->type = STRUCT;
-    getTypeAttributes(in, t);
+    getTypeAttributes(in, t, unnamed_types, named_types);
     getRAnglebracket(in); //<struct>
     getLAnglebracket(in); //<field name=..>
     token = getToken(in);
     sequence_init(&(t->fields));
     while(strcmp("field",token) == 0){
-      parseFields(in,t, unnamed_types, named_types);
+                       f = (field_t *)memAlloc(sizeof(field_t));
+                       sequence_push(&(t->fields),f);
+
+      parseFields(in, f, unnamed_types, named_types, 1);
       
       //next field
       getLAnglebracket(in);
@@ -607,15 +627,16 @@ type_descriptor_t *parseType(parse_file_t *in, type_descriptor_t *inType,
   }
   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>
+    getTypeAttributes(in, t, unnamed_types, named_types);
+    getRAnglebracket(in); //<union>
 
     getLAnglebracket(in); //<field name=..>
     token = getToken(in);
     sequence_init(&(t->fields));
     while(strcmp("field",token) == 0){
-      parseFields(in,t, unnamed_types, named_types);
+                       f = (field_t *)memAlloc(sizeof(field_t));
+                       sequence_push(&(t->fields),f);
+      parseFields(in, f, unnamed_types, named_types, 1);
       
       //next field
       getLAnglebracket(in);
@@ -629,12 +650,20 @@ type_descriptor_t *parseType(parse_file_t *in, type_descriptor_t *inType,
   }
   else if(strcmp(token,"array") == 0) {
     t->type = ARRAY;
-    getTypeAttributes(in, t);
-    if(t->size == -1) in->error(in, "Array has empty size");
+    sequence_init(&(t->fields));
+    getTypeAttributes(in, t, unnamed_types, named_types);
+    if(t->size == 0) in->error(in, "Array has empty size");
+    getForwardslash(in);
     getRAnglebracket(in); //<array size=n>
 
-    getLAnglebracket(in); //<type struct> 
-    t->nested_type = parseType(in, NULL, unnamed_types, named_types);
+    //getLAnglebracket(in); //<subtype> 
+               /* subfield */
+               f = (field_t *)memAlloc(sizeof(field_t));
+               sequence_push(&(t->fields),f);
+    parseFields(in, f, unnamed_types, named_types, 0);
+
+    //getLAnglebracket(in); //<type struct> 
+    //t->nested_type = parseType(in, NULL, unnamed_types, named_types);
 
     getLAnglebracket(in); //</array>
     getForwardslash(in);
@@ -644,12 +673,44 @@ type_descriptor_t *parseType(parse_file_t *in, type_descriptor_t *inType,
   }
   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>
-
-    getLAnglebracket(in); //<type struct> 
-    t->nested_type = parseType(in,NULL, unnamed_types, named_types);
+    sequence_init(&(t->fields));
+    //getTypeAttributes(in, t, unnamed_types, named_types);
+    //getForwardslash(in);
+    getRAnglebracket(in); //<sequence>
+
+    //getLAnglebracket(in); //<sequence size type> 
+               /* subfield */
+               f = (field_t *)memAlloc(sizeof(field_t));
+               sequence_push(&(t->fields),f);
+    parseFields(in, f, unnamed_types, named_types, 0);
+
+    //getLAnglebracket(in); //<subtype> 
+               /* subfield */
+               f = (field_t *)memAlloc(sizeof(field_t));
+               sequence_push(&(t->fields),f);
+    parseFields(in, f, unnamed_types, named_types, 0);
+
+    //getLAnglebracket(in); //<type sequence> 
+    //t->length_type = parseType(in, NULL, unnamed_types, named_types);
+
+    //getLAnglebracket(in); //<type sequence> 
+
+    //t->nested_type = parseType(in, NULL, unnamed_types, named_types);
+
+    if(t->fields.position < 1) in->error(in, "Sequence has no length type");
+    if(t->fields.position < 2) in->error(in, "Sequence has no subtype");
+               switch(((field_t*)t->fields.array[0])->type->type) {
+                       case UINT_FIXED :
+                       case UCHAR :
+                       case USHORT :
+                       case UINT :
+                       case ULONG :
+                       case SIZE_T :
+                       case OFF_T :
+                               break;
+                       default:
+                               in->error(in, "Wrong length type for sequence");
+               }
 
     getLAnglebracket(in); //</sequence>
     getForwardslash(in);
@@ -658,30 +719,38 @@ type_descriptor_t *parseType(parse_file_t *in, type_descriptor_t *inType,
     getRAnglebracket(in); //</sequence>
   }
   else if(strcmp(token,"enum") == 0) {
-    char * str, *str1;
+    char * str;
+    int value = -1;
+
     t->type = ENUM;
     sequence_init(&(t->labels));
+    sequence_init(&(t->labels_values));
     sequence_init(&(t->labels_description));
                t->already_printed = 0;
-    getTypeAttributes(in, t);
-    if(t->size == -1) in->error(in, "Sequence has empty size");
+    getTypeAttributes(in, t, unnamed_types, named_types);
+    //if(t->size == 0) in->error(in, "Sequence has empty size");
+               //Mathieu : we fix enum size to target int size. GCC is always like this.
+               //fox copy optimisation.
+    if(t->size != 0) in->error(in, "Enum has fixed size of target int.");
+               t->size = 0;
     getRAnglebracket(in);
 
     //<label name=label1 value=n/>
     getLAnglebracket(in);
     token = getToken(in); //"label" or "/"
     while(strcmp("label",token) == 0){
+      int *label_value = malloc(sizeof(int));
+      
       str   = allocAndCopy(getNameAttribute(in));      
       token = getValueStrAttribute(in);
-      if(token){
-       str1 = appendString(str,"=");
-       free(str);
-       str = appendString(str1,token);
-       free(str1);
-       sequence_push(&(t->labels),str);
-      }
-      else
-       sequence_push(&(t->labels),str);
+      
+       sequence_push(&(t->labels),str);
+
+      if(token) value = strtol(token, NULL, 0);
+      else value++;
+
+      *label_value = value;
+      sequence_push(&(t->labels_values), label_value);
 
       getForwardslash(in);
       getRAnglebracket(in);
@@ -699,81 +768,119 @@ type_descriptor_t *parseType(parse_file_t *in, type_descriptor_t *inType,
     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, unnamed_types, named_types);
+    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, unnamed_types, named_types);
+    if(t->size == 0) in->error(in, "uint has empty size");
+    getForwardslash(in);
+    getRAnglebracket(in); 
+  }
+  else if(strcmp(token,"char") == 0) {
+    t->type = CHAR;
+               t->size = 1;
+    getTypeAttributes(in, t, unnamed_types, named_types);
+    getForwardslash(in);
+    getRAnglebracket(in); 
+  }
+  else if(strcmp(token,"uchar") == 0) {
+    t->type = UCHAR;
+               t->size = 1;
+    getTypeAttributes(in, t, unnamed_types, named_types);
+    getForwardslash(in);
+    getRAnglebracket(in); 
+  }
+  else if(strcmp(token,"short") == 0) {
+    t->type = SHORT;
+               t->size = 2;
+    getTypeAttributes(in, t, unnamed_types, named_types);
+    getForwardslash(in);
+    getRAnglebracket(in); 
+  }
+  else if(strcmp(token,"ushort") == 0) {
+    t->type = USHORT;
+               t->size = 2;
+    getTypeAttributes(in, t, unnamed_types, named_types);
+    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");
+    getTypeAttributes(in, t, unnamed_types, named_types);
     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");
+    getTypeAttributes(in, t, unnamed_types, named_types);
     getForwardslash(in);
     getRAnglebracket(in); 
   }
+
   else if(strcmp(token,"pointer") == 0) {
     t->type = POINTER;
-    getTypeAttributes(in, t);
+    getTypeAttributes(in, t, unnamed_types, named_types);
     getForwardslash(in);
     getRAnglebracket(in); 
   }
   else if(strcmp(token,"long") == 0) {
     t->type = LONG;
-    getTypeAttributes(in, t);
+    getTypeAttributes(in, t, unnamed_types, named_types);
     getForwardslash(in);
     getRAnglebracket(in); 
   }
   else if(strcmp(token,"ulong") == 0) {
     t->type = ULONG;
-    getTypeAttributes(in, t);
+    getTypeAttributes(in, t, unnamed_types, named_types);
     getForwardslash(in);
     getRAnglebracket(in); 
   }
   else if(strcmp(token,"size_t") == 0) {
     t->type = SIZE_T;
-    getTypeAttributes(in, t);
+    getTypeAttributes(in, t, unnamed_types, named_types);
     getForwardslash(in);
     getRAnglebracket(in); 
   }
   else if(strcmp(token,"ssize_t") == 0) {
     t->type = SSIZE_T;
-    getTypeAttributes(in, t);
+    getTypeAttributes(in, t, unnamed_types, named_types);
     getForwardslash(in);
     getRAnglebracket(in); 
   }
   else if(strcmp(token,"off_t") == 0) {
     t->type = OFF_T;
-    getTypeAttributes(in, t);
+    getTypeAttributes(in, t, unnamed_types, named_types);
     getForwardslash(in);
     getRAnglebracket(in); 
   }
   else if(strcmp(token,"float") == 0) {
     t->type = FLOAT;
-    getTypeAttributes(in, t);
+    getTypeAttributes(in, t, unnamed_types, named_types);
     getForwardslash(in);
     getRAnglebracket(in); 
   }
   else if(strcmp(token,"string") == 0) {
     t->type = STRING;
-    getTypeAttributes(in, t);
+    getTypeAttributes(in, t, unnamed_types, named_types);
     getForwardslash(in);
     getRAnglebracket(in); 
   }
   else if(strcmp(token,"typeref") == 0){
     // Must be a named type
-    if(inType != NULL) 
-      in->error(in,"Named type cannot refer to a named type");
-    else {
-      free(t);
-      sequence_pop(unnamed_types);
-      token = getNameAttribute(in);
-      t = find_named_type(token, named_types);
-      getForwardslash(in);  //<typeref name=type_name/>
-      getRAnglebracket(in);
-      return t;
-    }
+               free(t);
+               sequence_pop(unnamed_types);
+               token = getNameAttribute(in);
+               t = find_named_type(token, named_types);
+               if(t == NULL) in->error(in,"Named referred to must be pre-declared.");
+               getForwardslash(in);  //<typeref name=type_name/>
+               getRAnglebracket(in);
+               return t;
   }else in->error(in,"not a valid type");
 
   return t;
@@ -794,16 +901,22 @@ type_descriptor_t * find_named_type(char *name, table_t * named_types)
   type_descriptor_t *t;
 
   t = table_find(named_types,name);
-  if(t == NULL) {
-    t = (type_descriptor_t *)memAlloc(sizeof(type_descriptor_t));
-    t->type_name = allocAndCopy(name);
-    t->type = NONE;
-    t->fmt = NULL;
-    table_insert(named_types,t->type_name,t);
-    //    table_insert(named_types,allocAndCopy(name),t);
-  }
+
   return t;
-}  
+}
+
+type_descriptor_t * create_named_type(char *name, table_t * named_types)
+{
+  type_descriptor_t *t;
+
+       t = (type_descriptor_t *)memAlloc(sizeof(type_descriptor_t));
+       t->type_name = allocAndCopy(name);
+       t->type = NONE;
+       t->fmt = NULL;
+       table_insert(named_types,t->type_name,t);
+       //    table_insert(named_types,allocAndCopy(name),t);
+       return t;
+}
 
 /*****************************************************************************
  *Function name
@@ -822,7 +935,7 @@ void parseTypeDefinition(parse_file_t * in, sequence_t * unnamed_types,
 
   token = getNameAttribute(in);
   if(token == NULL) in->error(in, "Type has empty name");
-  t = find_named_type(token, named_types);
+  t = create_named_type(token, named_types);
 
   if(t->type != NONE) in->error(in,"redefinition of named type");
   getRAnglebracket(in); //<type name=type_name>
@@ -877,7 +990,10 @@ char *getForwardslash(parse_file_t * in)
   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;
 }
 
@@ -1118,23 +1234,21 @@ void checkNamedTypesImplemented(table_t * named_types)
  ****************************************************************************/
 
 void generateChecksum(char* facName,
-    unsigned long * checksum, sequence_t * events)
+    unsigned int * checksum, sequence_t * events)
 {
   unsigned long crc ;
   int pos;
   event_t * ev;
-  char str[256];
 
   crc = crc32(facName);
   for(pos = 0; pos < events->position; pos++){
     ev = (event_t *)(events->array[pos]);
-    crc = partial_crc32(ev->name,crc);    
-    if(!ev->type) continue; //event without type
-    if(ev->type->type != STRUCT){
-      sprintf(str,"event '%s' has a type other than STRUCT",ev->name);
-      error_callback(NULL, str);
-    }
-    crc = getTypeChecksum(crc, ev->type);
+    crc = partial_crc32(ev->name, crc);
+               for(unsigned int i = 0; i < ev->fields.position; i++) {
+                       field_t *f = (field_t*)ev->fields.array[i];
+      crc = partial_crc32(f->name, crc);
+      crc = getTypeChecksum(crc, f->type);
+               }
   }
   *checksum = crc;
 }
@@ -1157,16 +1271,40 @@ unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor_t * type)
   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;
@@ -1188,23 +1326,24 @@ unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor_t * type)
                        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,"%zu", type->size);
       str = appendString("array ",buf);
       flag = 1;
       break;
     case SEQUENCE:
-      sprintf(buf,"%d",type->size);
+      sprintf(buf,"%zu", type->size);
       str = appendString("sequence ",buf);
       flag = 1;
       break;
@@ -1226,9 +1365,12 @@ unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor_t * type)
 
   if(type->fmt) crc = partial_crc32(type->fmt,crc);
     
-  if(type->type == ARRAY || type->type == SEQUENCE){
-    crc = getTypeChecksum(crc,type->nested_type);
-  }else if(type->type == STRUCT || type->type == UNION){
+  if(type->type == ARRAY){
+    crc = getTypeChecksum(crc,((field_t*)type->fields.array[0])->type);
+  } else if(type->type ==SEQUENCE) {
+    crc = getTypeChecksum(crc,((field_t*)type->fields.array[0])->type);
+    crc = getTypeChecksum(crc,((field_t*)type->fields.array[1])->type);
+       } else if(type->type == STRUCT || type->type == UNION){
     for(pos =0; pos < type->fields.position; pos++){
       fld = (field_t *) type->fields.array[pos];
       crc = partial_crc32(fld->name,crc);
@@ -1255,6 +1397,10 @@ void freeType(type_descriptor_t * tp)
       free(tp->labels.array[pos2]);
     }
     sequence_dispose(&(tp->labels));
+    for(pos2 = 0; pos2 < tp->labels_values.position; pos2++) {
+      free(tp->labels_values.array[pos2]);
+    }
+    sequence_dispose(&(tp->labels_values));
   }
   if(tp->type == STRUCT) {
     for(pos2 = 0; pos2 < tp->fields.position; pos2++) {
@@ -1301,6 +1447,7 @@ void freeEvents(sequence_t *t)
     ev = (event_t *) t->array[pos];
     free(ev->name);
     free(ev->description);
+               sequence_dispose(&ev->fields);
     free(ev);
   }
 
index c846697b89099338c938e9fef05784a738f6e133..21884fb6d0b82d35f44bd4cc12ee19e5f3e7a799 100644 (file)
@@ -77,9 +77,15 @@ static const int BUFFER_SIZE = 1024;
 /* Events data types */
 
 typedef enum _data_type {
+  INT_FIXED,
+  UINT_FIXED,
+       POINTER,
+       CHAR,
+       UCHAR,
+       SHORT,
+       USHORT,
   INT,
   UINT,
-       POINTER,
        LONG,
        ULONG,
        SIZE_T,
@@ -95,24 +101,21 @@ typedef enum _data_type {
   NONE
 } data_type_t;
 
-/* Event type descriptors */
-
 typedef struct _type_descriptor {
   char * type_name; //used for named type
   data_type_t type;
   char *fmt;
-  int size;
+  size_t size;
   sequence_t labels; // for enumeration
+  sequence_t labels_values; // for enumeration
        sequence_t labels_description;
        int     already_printed;
-  sequence_t fields; // for structure
-  struct _type_descriptor *nested_type; // for array and sequence 
-  int alignment;
+  sequence_t fields; // for structure, array and sequence (field_t type)
 } type_descriptor_t;
 
 
-/* Fields within types */
 
+/* Fields within types or events */
 typedef struct _field{
   char *name;
   char *description;
@@ -125,7 +128,8 @@ typedef struct _field{
 typedef struct _event {  
   char *name;
   char *description;
-  type_descriptor_t *type; 
+  //type_descriptor_t *type; 
+       sequence_t fields;      /* event fields */
   int  per_trace;   /* Is the event able to be logged to a specific trace ? */
   int  per_tracefile;  /* Must we log this event in a specific tracefile ? */
 } event_t;
@@ -135,11 +139,13 @@ typedef struct _facility {
        char * capname;
   char * description;
   sequence_t events;
-  sequence_t unnamed_types;
+  sequence_t unnamed_types; //FIXME : remove
   table_t named_types;
+       unsigned int checksum;
 } facility_t;
 
-int getSize(parse_file_t *in);
+int getSizeindex(unsigned int value);
+unsigned long long int getSize(parse_file_t *in);
 unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor_t * type);
 
 void parseFacility(parse_file_t *in, facility_t * fac);
@@ -149,12 +155,14 @@ void parseTypeDefinition(parse_file_t *in,
     sequence_t * unnamed_types, table_t * named_types);
 type_descriptor_t *parseType(parse_file_t *in,
     type_descriptor_t *t, sequence_t * unnamed_types, table_t * named_types);
-void parseFields(parse_file_t *in, type_descriptor_t *t,
-    sequence_t * unnamed_types, table_t * named_types);
+void parseFields(parse_file_t *in, field_t *f,
+    sequence_t * unnamed_types,
+               table_t * named_types,
+               int tag);
 void checkNamedTypesImplemented(table_t * namedTypes);
 type_descriptor_t * find_named_type(char *name, table_t * named_types);
 void generateChecksum(char * facName,
-    unsigned long * checksum, sequence_t * events);
+    unsigned int * checksum, sequence_t * events);
 
 
 /* get attributes */
@@ -206,4 +214,13 @@ crc32(const char *s)
 }
 
 
+extern char *intOutputTypes[];
+
+extern char *uintOutputTypes[];
+
+extern char *floatOutputTypes[];
+
+
+
+
 #endif // PARSER_H
index cdfab23fd2c3dc62d75a46fdac042b53ec0deb68..ec5152f3b7174bf0d65e46e835970177e6fe10d5 100644 (file)
@@ -78,16 +78,18 @@ GQuark LTT_TRACEFILE_NAME_FACILITIES;
 
 /* set the offset of the fields belonging to the event,
    need the information of the archecture */
-void set_fields_offsets(LttTracefile *tf, LttEventType *event_type);
+//void set_fields_offsets(LttTracefile *tf, LttEventType *event_type);
 //size_t get_fields_offsets(LttTracefile *tf, LttEventType *event_type, void *data);
 
 /* get the size of the field type according to 
  * The facility size information. */
+#if 0
 static inline void preset_field_type_size(LttTracefile *tf,
     LttEventType *event_type,
     off_t offset_root, off_t offset_parent,
     enum field_status *fixed_root, enum field_status *fixed_parent,
     LttField *field);
+#endif //0
 
 /* map a fixed size or a block information from the file (fd) */
 static gint map_block(LttTracefile * tf, guint block_num);
@@ -179,6 +181,8 @@ static void  parser_characters   (GMarkupParseContext __UNUSED__ *context,
   des->description = g_strdup(text);
 }
 #endif //0
+
+
 LttFacility *ltt_trace_get_facility_by_num(LttTrace *t,
     guint num)
 {
@@ -213,6 +217,7 @@ int parse_trace_header(void *header, LttTracefile *tf, LttTrace *t)
   /* Get float byte order : might be different from int byte order
    * (or is set to 0 if the trace has no float (kernel trace)) */
   tf->float_word_order = any->float_word_order;
+       tf->has_alignment = any->has_alignment;
 
   if(t) {
     t->arch_type = ltt_get_uint32(LTT_GET_BO(tf),
@@ -224,7 +229,6 @@ int parse_trace_header(void *header, LttTracefile *tf, LttTrace *t)
     t->ltt_minor_version = any->minor_version;
     t->flight_recorder = any->flight_recorder;
     t->has_heartbeat = any->has_heartbeat;
-    t->has_alignment = any->has_alignment;
     t->has_tsc = any->has_tsc;
   }
  
@@ -962,6 +966,8 @@ static int ltt_process_facility_tracefile(LttTracefile *tf)
           fac->id = ltt_get_uint32(LTT_GET_BO(tf), &fac_load_data->id);
           fac->pointer_size = ltt_get_uint32(LTT_GET_BO(tf),
                           &fac_load_data->pointer_size);
+                                       fac->int_size = ltt_get_uint32(LTT_GET_BO(tf),
+                                                                                                       &fac_load_data->int_size);
           fac->long_size = ltt_get_uint32(LTT_GET_BO(tf),
                           &fac_load_data->long_size);
           fac->size_t_size = ltt_get_uint32(LTT_GET_BO(tf),
@@ -977,7 +983,7 @@ static int ltt_process_facility_tracefile(LttTracefile *tf)
           /* Preset the field offsets */
           for(i=0; i<fac->events->len; i++){
             et = &g_array_index(fac->events, LttEventType, i);
-            set_fields_offsets(tf, et);
+            precompute_offsets(tf, et);
           }
 
           fac->exists = 1;
@@ -1016,6 +1022,8 @@ static int ltt_process_facility_tracefile(LttTracefile *tf)
                           &fac_state_dump_load_data->id);
           fac->pointer_size = ltt_get_uint32(LTT_GET_BO(tf),
                           &fac_state_dump_load_data->pointer_size);
+                                       fac->int_size = ltt_get_uint32(LTT_GET_BO(tf),
+                                                                                                       &fac_state_dump_load_data->int_size);
           fac->long_size = ltt_get_uint32(LTT_GET_BO(tf),
                           &fac_state_dump_load_data->long_size);
           fac->size_t_size = ltt_get_uint32(LTT_GET_BO(tf),
@@ -1030,7 +1038,7 @@ static int ltt_process_facility_tracefile(LttTracefile *tf)
           /* Preset the field offsets */
           for(i=0; i<fac->events->len; i++){
             et = &g_array_index(fac->events, LttEventType, i);
-            set_fields_offsets(tf, et);
+            precompute_offsets(tf, et);
           }
 
           fac->exists = 1;
@@ -1653,7 +1661,8 @@ int ltt_tracefile_read_update_event(LttTracefile *tf)
 
   /* Read event header */
   
-  //TODO align
+       /* Align the head */
+       pos += ltt_align(pos, tf->trace->arch_size, tf->has_alignment);
   
   if(tf->trace->has_tsc) {
     if(tf->trace->has_heartbeat) {
@@ -1701,6 +1710,9 @@ int ltt_tracefile_read_update_event(LttTracefile *tf)
   event->event_size = ltt_get_uint16(LTT_GET_BO(tf), pos);
   pos += sizeof(guint16);
   
+       /* Align the head */
+       pos += ltt_align(pos, tf->trace->arch_size, tf->has_alignment);
+
   event->data = pos;
 
   /* get the data size and update the event fields with the current
@@ -1834,7 +1846,7 @@ map_error:
 /* It will update the fields offsets too */
 void ltt_update_event_size(LttTracefile *tf)
 {
-  ssize_t size = 0;
+  size_t size = 0;
 
   /* Specific handling of core events : necessary to read the facility control
    * tracefile. */
@@ -1889,12 +1901,9 @@ void ltt_update_event_size(LttTracefile *tf)
           g_quark_to_string(tf->name));
       goto event_type_error;
     }
-    if(event_type->root_field)
-      size = get_field_type_size(tf, event_type,
-          0, 0, event_type->root_field, tf->event.data);
-    else
-      size = 0;
+    
+    /* Compute the dynamic offsets */
+    compute_offsets(tf, event_type, &size, tf->event.data);
 
     //g_debug("Event root field : f.e %hhu.%hhu size %zd",
     //    tf->event.facility_id,
@@ -2003,7 +2012,7 @@ void setFieldsOffset(LttTracefile *tf, LttEventType *evT,void *evD)
         evT, 0,0,rootFld, evD);  
 }
 #endif //0
-
+#if 0
 /*****************************************************************************
  *Function name
  *    set_fields_offsets : set the precomputable offset of the fields
@@ -2023,6 +2032,369 @@ void set_fields_offsets(LttTracefile *tf, LttEventType *event_type)
         field);
 
 }
+#endif //0
+
+
+/*****************************************************************************
+ *Function name
+ *    get_alignment : Get the alignment needed for a field.
+ *Input params 
+ *    tf : tracefile
+ *    field : field
+ *
+ *    returns : The size on which it must be aligned.
+ *
+ ****************************************************************************/
+off_t get_alignment(LttTracefile *tf, LttField *field)
+{
+  type = &field->field_type;
+
+  switch(type->type_class) {
+    case LTT_INT_FIXED:
+    case LTT_UINT_FIXED:
+    case LTT_POINTER:
+    case LTT_CHAR:
+    case LTT_UCHAR:
+    case LTT_SHORT:
+    case LTT_USHORT:
+    case LTT_INT:
+    case LTT_UINT:
+    case LTT_LONG:
+    case LTT_ULONG:
+    case LTT_SIZE_T:
+    case LTT_SSIZE_T:
+    case LTT_OFF_T:
+    case LTT_FLOAT:
+    case LTT_ENUM:
+      /* Align offset on type size */
+      return field->field_size;
+      break;
+    case LTT_STRING:
+      return 0;
+      break;
+    case LTT_ARRAY:
+      g_assert(type->fields->len == 1);
+      {
+        LttField *child = &g_array_index(type->fields, LttField, 0);
+        return get_alignment(tf, child);
+      }
+      break;
+    case LTT_SEQUENCE:
+      g_assert(type->fields->len == 2);
+      {
+        off_t localign = 0;
+        LttField *child = &g_array_index(type->fields, LttField, 0);
+
+        localign = max(localign, get_alignment(tf, child));
+
+        child = &g_array_index(type->fields, LttField, 1);
+        localign = max(localign, get_alignment(tf, child));
+        
+        return localign;
+      }
+      break;
+    case LTT_STRUCT:
+    case LTT_UNION:
+      {
+        guint i;
+        off_t localign = 0;
+        
+        for(i=0; i<type->fields->len; i++) {
+          LttField *child = &g_array_index(type->fields, LttField, i);
+          localign = max(localign, get_alignment(tf, child));
+        }
+        return localign;
+      }
+      break;
+    case LTT_NONE:
+    default:
+      g_error("get_alignment : unknown type");
+  }
+
+}
+
+/*****************************************************************************
+ *Function name
+ *    field_compute_static_size : Determine the size of fields known by their
+ *    sole definition. Unions, arrays and struct sizes might be known, but
+ *    the parser does not give that information.
+ *Input params 
+ *    tf : tracefile
+ *    field : field
+ *
+ ****************************************************************************/
+
+void field_compute_static_size(LttTracefile *tf, LttField *field)
+{
+  type = &field->field_type;
+
+  switch(type->type_class) {
+    case LTT_INT_FIXED:
+    case LTT_UINT_FIXED:
+    case LTT_POINTER:
+    case LTT_CHAR:
+    case LTT_UCHAR:
+    case LTT_SHORT:
+    case LTT_USHORT:
+    case LTT_INT:
+    case LTT_UINT:
+    case LTT_LONG:
+    case LTT_ULONG:
+    case LTT_SIZE_T:
+    case LTT_SSIZE_T:
+    case LTT_OFF_T:
+    case LTT_FLOAT:
+    case LTT_ENUM:
+    case LTT_STRING:
+      /* nothing to do */
+      break;
+    case LTT_ARRAY:
+      /* note this : array type size is the number of elements in the array,
+       * while array field size of the length of the array in bytes */
+      g_assert(type->fields->len == 1);
+      {
+        LttField *child = &g_array_index(type->fields, LttField, 0);
+        field_compute_static_size(tf, child);
+        
+        if(child->field_size != 0) {
+          field->field_size = type->size * child->field_size;
+          field->dynamic_offsets = g_array_sized_new(FALSE, TRUE, 
+              sizeof(off_t), type->size);
+        } else {
+          field->field_size = 0;
+        }
+      }
+      break;
+    case LTT_SEQUENCE:
+      g_assert(type->fields->len == 2);
+      {
+        local_offset = 0;
+        LttField *child = &g_array_index(type->fields, LttField, 1);
+        field_compute_static_size(tf, child);
+        field->field_size = 0;
+        type->size = 0;
+        if(child->field_size != 0) {
+          field->dynamic_offsets = g_array_sized_new(FALSE, TRUE, 
+              sizeof(off_t), SEQUENCE_AVG_ELEMENTS);
+        }
+      }
+      break;
+    case LTT_STRUCT:
+    case LTT_UNION:
+      {
+        guint i;
+        for(i=0;i<type->fields->len;i++) {
+          LttField *child = &g_array_index(type->fields, LttField, i);
+          field_compute_static_size(tf, child);
+          if(child->field_size != 0) {
+            type->size += ltt_align(type->size, get_alignment(tf, child),
+                                    tf->has_alignment);
+            type->size += child->field_size;
+          } else {
+            /* As soon as we find a child with variable size, we have
+             * a variable size */
+            type->size = 0;
+            break;
+          }
+        }
+        field->field_size = type->size;
+      }
+      break;
+    default:
+      g_error("field_static_size : unknown type");
+      
+}
+
+
+
+/*****************************************************************************
+ *Function name
+ *    precompute_fields_offsets : set the precomputable offset of the fields
+ *Input params 
+ *    tf : tracefile
+ *    field : the field
+ *    offset : pointer to the current offset, must be incremented
+ *
+ *    return : 1 : found a variable length field, stop the processing.
+ *             0 otherwise.
+ ****************************************************************************/
+
+
+gint precompute_fields_offsets(LttTracefile *tf, LttField *field, off_t *offset)
+{
+  type = &field->field_type;
+
+  switch(type->type_class) {
+    case LTT_INT_FIXED:
+    case LTT_UINT_FIXED:
+    case LTT_POINTER:
+    case LTT_CHAR:
+    case LTT_UCHAR:
+    case LTT_SHORT:
+    case LTT_USHORT:
+    case LTT_INT:
+    case LTT_UINT:
+    case LTT_LONG:
+    case LTT_ULONG:
+    case LTT_SIZE_T:
+    case LTT_SSIZE_T:
+    case LTT_OFF_T:
+    case LTT_FLOAT:
+    case LTT_ENUM:
+      /* Align offset on type size */
+      *offset += ltt_align(*offset, get_alignment(tf, field),
+                           tf->has_alignment);
+      /* remember offset */
+      field->offset_root = *offset;
+      field->fixed_root = FIELD_FIXED;
+      /* Increment offset */
+      *offset += field->field_size;
+      return 0;
+      break;
+    case LTT_STRING:
+      field->offset_root = *offset;
+      field->fixed_root = FIELD_FIXED;
+      return 1;
+      break;
+    case LTT_ARRAY:
+      g_assert(type->fields->len == 1);
+      {
+        LttField *child = &g_array_index(type->fields, LttField, 0);
+
+        *offset += ltt_align(*offset, get_alignment(tf, field),
+                            tf->has_alignment);
+        
+        /* remember offset */
+        field->offset_root = *offset;
+        field->array_offset = *offset;
+        field->fixed_root = FIELD_FIXED;
+
+        /* Let the child be variable */
+        //precompute_fields_offsets(tf, child, offset);
+      
+        if(field->field_size != 0) {
+          /* Increment offset */
+          /* field_size is the array size in bytes */
+          *offset += field->field_size;
+          return 0;
+        } else {
+          return 1;
+        }
+      }
+      break;
+    case LTT_SEQUENCE:
+      g_assert(type->fields->len == 2);
+      {
+        LttField *child;
+        guint ret;
+
+        *offset += ltt_align(*offset, get_alignment(tf, field),
+                             tf->has_alignment);
+
+        /* remember offset */
+        field->offset_root = *offset;
+        field->fixed_root = FIELD_FIXED;
+        child = &g_array_index(type->fields, LttField, 0);
+        ret = precompute_fields_offsets(tf, child, offset);
+        g_assert(ret == 0); /* Seq len cannot have variable len */
+
+        child = &g_array_index(type->fields, LttField, 1);
+        *offset += ltt_align(*offset, get_alignment(tf, child),
+                             tf->has_alignment);
+        field->array_offset = *offset;
+        /* Set the offset position at position 0 */
+        ret = precompute_fields_offsets(tf, child, offset);
+
+        /* Cannot precompute fields offsets of sequence members, and has
+         * variable length. */
+        return 1;
+      }
+      break;
+    case LTT_STRUCT:
+      { 
+        LttField *child;
+        guint i;
+        gint ret=0;
+
+        *offset += ltt_align(*offset, get_alignment(tf, field),
+                             tf->has_alignment);
+        /* remember offset */
+        field->offset_root = *offset;
+        field->fixed_root = FIELD_FIXED;
+
+        for(i=0; i< type->fields->len; i++) {
+          child = &g_array_index(type->fields, LttField, i);
+          ret = precompute_fields_offsets(tf, child, offset);
+
+          if(ret) break;
+        }
+        return ret;
+      }
+      break;
+    case LTT_UNION:
+      { 
+        LttField *child;
+        guint i;
+        gint ret=0;
+
+        *offset += ltt_align(*offset, get_alignment(tf, field),
+                             tf->has_alignment);
+        /* remember offset */
+        field->offset_root = *offset;
+        field->fixed_root = FIELD_FIXED;
+
+        for(i=0; i< type->fields->len; i++) {
+          *offset = field->offset_root;
+          child = &g_array_index(type->fields, LttField, i);
+          ret = precompute_fields_offsets(tf, child, offset);
+
+          if(ret) break;
+        }
+        *offset = field->offset_root + field->field_size;
+        return ret;
+      }
+
+      break;
+    case LTT_NONE:
+    default:
+      g_error("precompute_fields_offsets : unknown type");
+      return 1;
+  }
+
+}
+
+
+/*****************************************************************************
+ *Function name
+ *    precompute_offsets : set the precomputable offset of an event type
+ *Input params 
+ *    tf : tracefile
+ *    event : event type
+ *
+ ****************************************************************************/
+void precompute_offsets(LttTracefile *tf, LttEventType *event)
+{
+  guint i;
+  off_t offset = 0;
+  gint ret;
+
+  /* First, compute the size of fixed size fields. Will determine size for
+   * arrays, struct and unions, which is not done by the parser */
+  for(i=0; i<event->fields->len; i++) {
+    LttField *field = &g_array_index(event->fields, LttField, i);
+    field_compute_static_size(tf, field);
+  }
+  
+  /* Precompute all known offsets */
+  for(i=0; i<event->fields->len; i++) {
+    LttField *field = &g_array_index(event->fields, LttField, i);
+    ret = precompute_fields_offsets(tf, field, &offset);
+    if(ret) break;
+  }
+}
+
+
 
 
 /*****************************************************************************
@@ -2037,6 +2409,15 @@ void set_fields_offsets(LttTracefile *tf, LttEventType *event_type)
  *    fixed_parent    : Do we know a fixed offset to the parent ?
  *    field           : field
  ****************************************************************************/
+
+
+
+// preset the fixed size offsets. Calculate them just like genevent-new : an
+// increment of a *to value that represents the offset from the start of the
+// event data.
+// The preset information is : offsets up to (and including) the first element
+// of variable size. All subsequent fields must be flagged "VARIABLE OFFSET".
+#if 0
 void preset_field_type_size(LttTracefile *tf, LttEventType *event_type,
     off_t offset_root, off_t offset_parent,
     enum field_status *fixed_root, enum field_status *fixed_parent,
@@ -2184,7 +2565,7 @@ void preset_field_type_size(LttTracefile *tf, LttEventType *event_type,
   }
 
 }
-
+#endif //0
 
 /*****************************************************************************
  *Function name
@@ -2198,6 +2579,112 @@ void preset_field_type_size(LttTracefile *tf, LttEventType *event_type,
  *Returns : 0 if identical
  *          1 if not.
  ****************************************************************************/
+// this function checks for equality of field types. Therefore, it does not use
+// per se offsets. For instance, an aligned version of a structure is
+// compatible with an unaligned version of the same structure.
+gint check_fields_compatibility(LttEventType *event_type1,
+    LttEventType *event_type2,
+    LttField *field1, LttField *field2)
+{
+  guint different = 0;
+
+  if(field1 == NULL) {
+    if(field2 == NULL) goto end;
+    else {
+      different = 1;
+      goto end;
+    }
+  } else if(field2 == NULL) {
+    different = 1;
+    goto end;
+  }
+
+  type1 = field1->field_type;
+  type2 = field2->field_type;
+
+  if(type1->type_class != type2->type_class) {
+    different = 1;
+    goto end;
+  }
+  if(type1->element_name != type2->element_name) {
+    different = 1;
+    goto end;
+  }
+  switch(type1->type_class) {
+    case LTT_INT_FIXED:
+    case LTT_UINT_FIXED:
+    case LTT_POINTER:
+    case LTT_CHAR:
+    case LTT_UCHAR:
+    case LTT_SHORT:
+    case LTT_USHORT:
+    case LTT_INT:
+    case LTT_UINT:
+    case LTT_LONG:
+    case LTT_ULONG:
+    case LTT_SIZE_T:
+    case LTT_SSIZE_T:
+    case LTT_OFF_T:
+    case LTT_FLOAT:
+    case LTT_ENUM:
+      if(field1->field_size != field2->field_size)
+        different = 1;
+      break;
+    case LTT_STRING:
+      break;
+    case LTT_ARRAY:
+      {
+        LttField *child1 = &g_array_index(type1->fields, LttField, 0);
+        LttField *child2 = &g_array_index(type2->fields, LttField, 0);
+
+        if(type1->size != type2->size)
+          different = 1;
+        if(check_fields_compatibility(event_type1, event_type2, child1, child2))
+          different = 1;
+      }
+      break;
+    case LTT_SEQUENCE:
+      {
+        LttField *child1 = &g_array_index(type1->fields, LttField, 1);
+        LttField *child2 = &g_array_index(type2->fields, LttField, 1);
+
+        if(check_fields_compatibility(event_type1, event_type2, child1, child2))
+          different = 1;
+      }
+      break;
+    case LTT_STRUCT:
+    case LTT_UNION:
+      { 
+        LttField *child;
+        guint i;
+        
+        if(type1->fields->len != type2->fields->len) {
+          different = 1;
+          goto end;
+        }
+        
+        for(i=0; i< type1->fields->len; i++) {
+          child1 = &g_array_index(type1->fields, LttField, i);
+          child2 = &g_array_index(type2->fields, LttField, i);
+          different = check_fields_compatibility(event_type1,
+                        event_type2, child1, child2);
+
+          if(different) break;
+        }
+      }
+      break;
+    case LTT_NONE:
+    default:
+      g_error("precompute_fields_offsets : unknown type");
+  }
+
+end:
+  return different;
+}
+
+
+#if 0
 gint check_fields_compatibility(LttEventType *event_type1,
     LttEventType *event_type2,
     LttField *field1, LttField *field2)
@@ -2310,176 +2797,9 @@ gint check_fields_compatibility(LttEventType *event_type1,
 end:
   return different;
 }
-
-
-
-
-#if 0
-/*****************************************************************************
- *Function name
- *    getFieldtypeSize: get the size of the field type (primitive type)
- *Input params 
- *    evT             : event type
- *    offsetRoot      : offset from the root
- *    offsetParent    : offset from the parrent
- *    fld             : field
- *    evD             : event data, it may be NULL
- *Return value
- *    int             : size of the field
- ****************************************************************************/
-
-static inline gint getFieldtypeSize(LttTracefile *tf,
-       LttEventType * evT, gint offsetRoot,
-            gint offsetParent, LttField * fld, void *evD)
-{
-  gint size, size1, element_number, i, offset1, offset2;
-  LttType * type = fld->field_type;
-
-  /* This likely has been tested with gcov : half of them.. */
-  if(unlikely(fld->field_fixed == 1)){
-    /* tested : none */
-    if(unlikely(fld == evT->root_field)) {
-      size = fld->field_size;
-      goto end_getFieldtypeSize;
-    }
-  }
-
-  /* From gcov profiling : half string, half struct, can we gain something
-   * from that ? (Mathieu) */
-  switch(type->type_class) {
-    case LTT_ARRAY:
-      element_number = (int) type->element_number;
-      if(fld->field_fixed == -1){
-        size = getFieldtypeSize(tf, evT, offsetRoot,
-                                0,fld->child[0], NULL);
-        if(size == 0){ //has string or sequence
-          fld->field_fixed = 0;
-        }else{
-          fld->field_fixed = 1;
-          size *= element_number; 
-        }
-      }else if(fld->field_fixed == 0){// has string or sequence
-        size = 0;
-        for(i=0;i<element_number;i++){
-          size += getFieldtypeSize(tf, evT, offsetRoot+size,size, 
-          fld->child[0], evD+size);
-        }
-      }else size = fld->field_size;
-      if(unlikely(!evD)){
-        fld->fixed_root    = (offsetRoot==-1)   ? 0 : 1;
-        fld->fixed_parent  = (offsetParent==-1) ? 0 : 1;
-      }
-
-      break;
-
-    case LTT_SEQUENCE:
-      size1 = (int) ltt_type_size(fac, type);
-      if(fld->field_fixed == -1){
-        fld->sequ_number_size = size1;
-        fld->field_fixed = 0;
-        size = getFieldtypeSize(evT, offsetRoot,
-                                0,fld->child[0], NULL);      
-        fld->element_size = size;
-      }else{//0: sequence
-        element_number = getIntNumber(tf,size1,evD);
-        type->element_number = element_number;
-        if(fld->element_size > 0){
-          size = element_number * fld->element_size;
-        }else{//sequence has string or sequence
-          size = 0;
-          for(i=0;i<element_number;i++){
-            size += getFieldtypeSize(tf, evT,
-                                     offsetRoot+size+size1,size+size1, 
-                                     fld->child[0], evD+size+size1);
-          }
-        }
-        size += size1;
-      }
-      if(unlikely(!evD)){
-        fld->fixed_root    = (offsetRoot==-1)   ? 0 : 1;
-        fld->fixed_parent  = (offsetParent==-1) ? 0 : 1;
-      }
-
-      break;
-      
-    case LTT_STRING:
-      size = 0;
-      if(fld->field_fixed == -1){
-        fld->field_fixed = 0;
-      }else{//0: string
-        /* Hope my implementation is faster than strlen (Mathieu) */
-        char *ptr=(char*)evD;
-        size = 1;
-        /* from gcov : many many strings are empty, make it the common case.*/
-        while(unlikely(*ptr != '\0')) { size++; ptr++; }
-        //size = ptr - (char*)evD + 1; //include end : '\0'
-      }
-      fld->fixed_root    = (offsetRoot==-1)   ? 0 : 1;
-      fld->fixed_parent  = (offsetParent==-1) ? 0 : 1;
-
-      break;
-      
-    case LTT_STRUCT:
-      element_number = (int) type->element_number;
-      size = 0;
-      /* tested with gcov */
-      if(unlikely(fld->field_fixed == -1)){
-        offset1 = offsetRoot;
-        offset2 = 0;
-        for(i=0;i<element_number;i++){
-          size1=getFieldtypeSize(tf, evT,offset1,offset2,
-                                 fld->child[i], NULL);
-          if(likely(size1 > 0 && size >= 0)){
-            size += size1;
-            if(likely(offset1 >= 0)) offset1 += size1;
-              offset2 += size1;
-          }else{
-            size = -1;
-            offset1 = -1;
-            offset2 = -1;
-          }
-        }
-        if(unlikely(size == -1)){
-           fld->field_fixed = 0;
-           size = 0;
-        }else fld->field_fixed = 1;
-      }else if(likely(fld->field_fixed == 0)){
-        offset1 = offsetRoot;
-        offset2 = 0;
-        for(i=0;unlikely(i<element_number);i++){
-          size=getFieldtypeSize(tf, evT, offset1, offset2,
-                                fld->child[i], evD+offset2);
-          offset1 += size;
-          offset2 += size;
-        }      
-        size = offset2;
-      }else size = fld->field_size;
-      fld->fixed_root    = (offsetRoot==-1)   ? 0 : 1;
-      fld->fixed_parent  = (offsetParent==-1) ? 0 : 1;
-      break;
-
-    default:
-      if(unlikely(fld->field_fixed == -1)){
-        size = (int) ltt_type_size(LTT_GET_BO(tf), type);
-        fld->field_fixed = 1;
-      }else size = fld->field_size;
-      if(unlikely(!evD)){
-        fld->fixed_root    = (offsetRoot==-1)   ? 0 : 1;
-        fld->fixed_parent  = (offsetParent==-1) ? 0 : 1;
-      }
-      break;
-  }
-
-  fld->offset_root     = offsetRoot;
-  fld->offset_parent   = offsetParent;
-  fld->field_size      = size;
-
-end_getFieldtypeSize:
-
-  return size;
-}
 #endif //0
 
+
 /*****************************************************************************
  *Function name
  *    ltt_get_int    : get an integer number
This page took 0.054427 seconds and 4 git commands to generate.