first version of reading api source files
authoryangxx <yangxx@04897980-b3bd-0310-b5e0-8ef037075253>
Fri, 30 May 2003 19:17:22 +0000 (19:17 +0000)
committeryangxx <yangxx@04897980-b3bd-0310-b5e0-8ef037075253>
Fri, 30 May 2003 19:17:22 +0000 (19:17 +0000)
git-svn-id: http://ltt.polymtl.ca/svn@60 04897980-b3bd-0310-b5e0-8ef037075253

ltt/branches/poly/ltt/LTTTypes.h [new file with mode: 0644]
ltt/branches/poly/ltt/crc32.tab [new file with mode: 0644]
ltt/branches/poly/ltt/event.c [new file with mode: 0644]
ltt/branches/poly/ltt/facility.c [new file with mode: 0644]
ltt/branches/poly/ltt/parser.c [new file with mode: 0644]
ltt/branches/poly/ltt/parser.h [new file with mode: 0644]
ltt/branches/poly/ltt/tracefile.c [new file with mode: 0644]
ltt/branches/poly/ltt/type.c [new file with mode: 0644]

diff --git a/ltt/branches/poly/ltt/LTTTypes.h b/ltt/branches/poly/ltt/LTTTypes.h
new file mode 100644 (file)
index 0000000..2c054a1
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * LTTTypes.h
+ *
+ * Copyright (C) 2000 Karim Yaghmour (karym@opersys.com).
+ *
+ * This is distributed under GPL.
+ *
+ * Header for LTT-secific types.
+ *
+ * History : 
+ *    K.Y.  07/09/2001, Added David Schleef's architecture independent ltt_set_bit/ltt_clear_bit/ltt_test_bit
+ *    JAL,  05/01/2001, Modified PPC bit manipulation functions for x86 compatibility.
+ *                      (andy_lowe@mvista.com)
+ *    K.Y., 31/05/2000, Initial typing.
+ */
+
+#ifndef __TRACE_TOOLKIT_TYPES_HEADER__
+#define __TRACE_TOOLKIT_TYPES_HEADER__
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#if defined(sun)
+
+typedef unsigned char          u_int8_t;
+typedef unsigned short         u_int16_t;
+typedef unsigned int           u_int32_t;
+#ifdef _LP64
+typedef unsigned long          u_int64_t;
+#else  /* _ILP32 */
+#if __STDC__ - 0 == 0 && !defined(_NO_LONGLONG)
+typedef unsigned long long     u_int64_t;
+#endif /* __STDC__ - 0 == 0 && !defined(_NO_LONGLONG) */
+#endif /* _LP64 */
+
+#endif /* defined(sun) */
+
+extern __inline__ int ltt_set_bit(int nr, void * addr)
+{
+  unsigned char *p = addr;
+  unsigned char mask = 1 << (nr&7);
+  unsigned char old;
+
+  p += nr>>3;
+  old = *p;
+  *p |= mask;
+  return ((old & mask) != 0);
+}
+
+extern __inline__ int ltt_clear_bit(int nr, void * addr)
+{
+  unsigned char *p = addr;
+  unsigned char mask = 1 << (nr&7);
+  unsigned char old;
+
+  p += nr>>3;
+  old = *p;
+  *p &= ~mask;
+  return ((old & mask) != 0);
+}
+
+extern __inline__ int ltt_test_bit(int nr,void *addr)
+{
+  unsigned char *p = addr;
+  unsigned char mask = 1 << (nr&7);
+  p += nr>>3;
+  return ((*p & mask) != 0);
+}
+
+/* Big-endian/little-endian conversion macros for cross-development. */
+#if TARGET_NATIVE
+/* For native development, these conversion macros aren't needed. */
+#define BREV16(x)   (x)
+#define BREV32(x)   (x)
+#define BREV64(x)   (x)
+#define RFT8(db,x)  (x)
+#define RFT16(db,x) (x)
+#define RFT32(db,x) (x)
+#define RFT64(db,x) (x)
+
+/* Non-native development */
+#else
+        /* BREV16: byte-reverse a 16-bit integer */
+#define BREV16(x) ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8))
+       /* BREV32: byte-reverse a 32-bit integer */
+#define BREV32(x) ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \
+                | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
+       /* BREV64: byte-reverse a 64-bit integer */
+#define BREV64(x) ((((x) & 0xff00000000000000) >> 56) \
+                 | (((x) & 0x00ff000000000000) >> 40) \
+                | (((x) & 0x0000ff0000000000) >> 24) \
+                | (((x) & 0x000000ff00000000) >>  8) \
+                | (((x) & 0x00000000ff000000) <<  8) \
+                | (((x) & 0x0000000000ff0000) << 24) \
+                | (((x) & 0x000000000000ff00) << 40) \
+                | (((x) & 0x00000000000000ff) << 56))
+       /* RFTn: Read From Trace
+        *      Conditionally byte-reverse an 8-, 16-, 32-, or 64-bit integer
+        *      based on the value of the ByteRev member of the trace database
+        *      structure pointer passed as the first argument..
+        */
+#define RFT8(db,x)  (x)
+#define RFT16(db,x) ((db)->ByteRev ? BREV16(x) : (x))
+#define RFT32(db,x) ((db)->ByteRev ? BREV32(x) : (x))
+#define RFT64(db,x) ((db)->ByteRev ? BREV64(x) : (x))
+#endif /* TRACE_TARGET_NATIVE */
+
+#if !defined(sun)
+/* Some type corrections, just in case */
+#ifndef uint8_t
+#define uint8_t u_int8_t
+#endif
+#ifndef uint16_t
+#define uint16_t u_int16_t
+#endif
+#ifndef uint32_t
+#define uint32_t u_int32_t
+#endif
+#ifndef uint64_t
+#define uint64_t u_int64_t
+#endif
+#endif /* !defined(sun) */
+
+/* Structure packing */
+#if LTT_UNPACKED_STRUCTS
+#define LTT_PACKED_STRUCT
+#else
+#define LTT_PACKED_STRUCT __attribute__ ((packed))
+#endif /* UNPACKED_STRUCTS */
+
+/* Trace mask */
+typedef uint64_t trace_event_mask;
+
+/* Boolean stuff */
+#define TRUE  1
+#define FALSE 0
+
+#endif /* __TRACE_TOOLKIT_TYPES_HEADER__ */
diff --git a/ltt/branches/poly/ltt/crc32.tab b/ltt/branches/poly/ltt/crc32.tab
new file mode 100644 (file)
index 0000000..d0174ad
--- /dev/null
@@ -0,0 +1,52 @@
+  0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U,
+  0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U,
+  0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U,
+  0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU,
+  0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U,
+  0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
+  0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U,
+  0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU,
+  0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U,
+  0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU,
+  0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U,
+  0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
+  0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U,
+  0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU,
+  0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU,
+  0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U,
+  0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU,
+  0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
+  0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U,
+  0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U,
+  0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU,
+  0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U,
+  0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U,
+  0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
+  0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U,
+  0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U,
+  0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U,
+  0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U,
+  0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U,
+  0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
+  0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU,
+  0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U,
+  0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U,
+  0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU,
+  0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU,
+  0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
+  0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU,
+  0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U,
+  0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU,
+  0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U,
+  0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU,
+  0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
+  0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U,
+  0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU,
+  0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U,
+  0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U,
+  0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U,
+  0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
+  0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U,
+  0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U,
+  0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU,
+  0x2d02ef8dU
diff --git a/ltt/branches/poly/ltt/event.c b/ltt/branches/poly/ltt/event.c
new file mode 100644 (file)
index 0000000..20d71d9
--- /dev/null
@@ -0,0 +1,350 @@
+#include <stdio.h>
+#include <asm/types.h>
+#include <linux/byteorder/swab.h>
+
+#include "LTTTypes.h"  
+#include "parser.h"
+#include <ltt/event.h>
+
+/*****************************************************************************
+ *Function name
+ *    ltt_facility_eventtype_id: get event type id 
+ *                               (base id + position of the event)
+ *Input params
+ *    e                        : an instance of an event type   
+ *Return value
+ *    unsigned                 : event type id
+ ****************************************************************************/
+
+unsigned ltt_event_eventtype_id(ltt_event *e)
+{
+  return (unsigned) e->event_id;
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_event_facility : get the facility of the event
+ *Input params
+ *    e                  : an instance of an event type   
+ *Return value
+ *    ltt_facility *     : the facility of the event
+ ****************************************************************************/
+
+ltt_facility *ltt_event_facility(ltt_event *e)
+{
+  ltt_eventtype * evT;
+  ptr_wrap * ptr;
+  ptr = (ptr_wrap*)g_ptr_array_index(e->tracefile->eventtype_event_id, 
+                                         (gint)(e->event_id));
+  evT = (ltt_eventtype*)(ptr->ptr);
+
+  if(!evT) return NULL;
+  return evT->facility;
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_event_eventtype : get the event type of the event
+ *Input params
+ *    e                   : an instance of an event type   
+ *Return value
+ *    ltt_eventtype *     : the event type of the event
+ ****************************************************************************/
+
+ltt_eventtype *ltt_event_eventtype(ltt_event *e)
+{
+  ptr_wrap * ptr;
+  ptr = (ptr_wrap*)g_ptr_array_index(e->tracefile->eventtype_event_id, 
+                                         (gint)(e->event_id));
+  return (ltt_eventtype*)(ptr->ptr);
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_event_time : get the time of the event
+ *Input params
+ *    e              : an instance of an event type   
+ *Return value
+ *    ltt_time       : the time of the event
+ ****************************************************************************/
+
+ltt_time ltt_event_time(ltt_event *e)
+{
+  return getEventTime(e->tracefile);
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_event_time : get the cycle count of the event
+ *Input params
+ *    e              : an instance of an event type   
+ *Return value
+ *    ltt_time       : the cycle count of the event
+ ****************************************************************************/
+
+ltt_cycle_count ltt_event_cycle_count(ltt_event *e)
+{
+  return e->cycle_count;
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_event_cpu_i: get the cpu id where the event happens
+ *Input params
+ *    e              : an instance of an event type   
+ *Return value
+ *    unsigned       : the cpu id
+ ****************************************************************************/
+
+unsigned ltt_event_cpu_id(ltt_event *e)
+{
+  return e->tracefile->trace_header->cpu_id;
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_event_cpu_i: get the name of the system where the event happens
+ *Input params
+ *    e              : an instance of an event type   
+ *Return value
+ *    char *         : the name of the system
+ ****************************************************************************/
+
+char *ltt_event_system_name(ltt_event *e)
+{
+  return e->tracefile->trace_header->system_name;  
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_event_data : get the raw data for the event
+ *Input params
+ *    e              : an instance of an event type   
+ *Return value
+ *    void *         : pointer to the raw data for the event
+ ****************************************************************************/
+
+void *ltt_event_data(ltt_event *e)
+{
+  return e->data;
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_event_field_element_number
+ *                   : The number of elements in a sequence field is specific
+ *                     to each event. This function returns the number of 
+ *                     elements for an array or sequence field in an event.
+ *Input params
+ *    e              : an instance of an event type   ????
+ *    f              : a field of the instance
+ *Return value
+ *    unsigned       : the number of elements for an array/sequence field
+ ****************************************************************************/
+
+unsigned ltt_event_field_element_number(ltt_event *e, ltt_field *f)
+{
+  if(f->field_type->type_class != LTT_ARRAY &&
+     f->field_type->type_class != LTT_SEQUENCE)
+    return 0;
+
+  return f->field_type->element_number;
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_event_field_element_select
+ *                   : Set the currently selected element for a sequence or
+ *                     array field
+ *Input params
+ *    e              : an instance of an event type   ????
+ *    f              : a field of the instance
+ *    i              : the ith element
+ *Return value
+ *    int            : ???? error number
+ ****************************************************************************/
+
+int ltt_event_field_element_select(ltt_event *e, ltt_field *f, unsigned i)
+{
+   if(f->field_type->type_class != LTT_ARRAY &&
+     f->field_type->type_class != LTT_SEQUENCE)
+     return -1; //?????
+   
+   if(f->field_type->element_number < i || i == 0) return -1; //????
+
+   f->current_element = i - 1;
+   return 0;
+}
+
+/*****************************************************************************
+ * These functions extract data from an event after architecture specific
+ * conversions
+ ****************************************************************************/
+
+unsigned ltt_event_get_unsigned(ltt_event *e, ltt_field *f)
+{
+  ltt_arch_size rSize = e->tracefile->trace_header->arch_size;
+  int revFlag = e->tracefile->my_arch_endian == 
+                e->tracefile->trace_header->arch_endian ? 0:1;
+  ltt_type_enum t = f->field_type->type_class;
+
+  if(t != LTT_UINT || t != LTT_ENUM)
+    g_error("The type of the field is not unsigned int\n");
+
+  if(rSize == LTT_LP32){
+    if(f->field_size != 2)
+      g_error("The type of the field is not unsigned int: uint16_t\n");
+    else{
+      uint16_t x = *(uint16_t *)(e->data + f->offset_root);
+      return (unsigned) (revFlag ? BREV16(x) : x); 
+    }
+  }else if(rSize == LTT_ILP32 || rSize == LTT_LP64){
+    if(f->field_size != 4)
+      g_error("The type of the field is not unsigned int: uint32_t\n");
+    else{
+      uint32_t x = *(uint32_t *)(e->data + f->offset_root);
+      return (unsigned) (revFlag ? BREV32(x): x);
+    }
+  }else if(rSize == LTT_ILP64){
+    if(f->field_size != 8)
+      g_error("The type of the field is not unsigned int: uint64_t\n");
+    else{
+      uint64_t x = *(uint64_t *)(e->data + f->offset_root);
+      return (unsigned) (revFlag ? BREV64(x): x);
+    }
+  }
+}
+
+int ltt_event_get_int(ltt_event *e, ltt_field *f)
+{
+  ltt_arch_size rSize = e->tracefile->trace_header->arch_size;
+  int revFlag = e->tracefile->my_arch_endian == 
+                e->tracefile->trace_header->arch_endian ? 0:1;
+
+  if(f->field_type->type_class != LTT_INT)
+    g_error("The type of the field is not int\n");
+
+  if(rSize == LTT_LP32){
+    if(f->field_size != 2)
+      g_error("The type of the field is not int: int16_t\n");
+    else{
+      int16_t x = *(int16_t *)(e->data + f->offset_root);
+      return (int) (revFlag ? BREV16(x) : x); 
+    }
+  }else if(rSize == LTT_ILP32 || rSize == LTT_LP64){
+    if(f->field_size != 4)
+      g_error("The type of the field is not int: int32_t\n");
+    else{
+      int32_t x = *(int32_t *)(e->data + f->offset_root);
+      return (int) (revFlag ? BREV32(x): x);
+    }
+  }else if(rSize == LTT_ILP64){
+    if(f->field_size != 8)
+      g_error("The type of the field is not int: int64_t\n");
+    else{
+      int64_t x = *(int64_t *)(e->data + f->offset_root);
+      return (int) (revFlag ? BREV64(x): x);
+    }
+  }
+}
+
+unsigned long ltt_event_get_long_unsigned(ltt_event *e, ltt_field *f)
+{
+  ltt_arch_size rSize = e->tracefile->trace_header->arch_size;
+  int revFlag = e->tracefile->my_arch_endian == 
+                e->tracefile->trace_header->arch_endian ? 0:1;
+  ltt_type_enum t = f->field_type->type_class;
+
+  if(t != LTT_UINT || t != LTT_ENUM)
+    g_error("The type of the field is not unsigned long\n");
+
+  if(rSize == LTT_LP32 || rSize == LTT_ILP32 ){
+    if(f->field_size != 4)
+      g_error("The type of the field is not unsigned long: uint32_t\n");
+    else{
+      uint32_t x = *(uint32_t *)(e->data + f->offset_root);
+      return (unsigned long) (revFlag ? BREV32(x) : x); 
+    }
+  }else if(rSize == LTT_LP64 || rSize == LTT_ILP64){
+    if(f->field_size != 8)
+      g_error("The type of the field is not unsigned long: uint64_t\n");
+    else{
+      uint64_t x = *(uint64_t *)(e->data + f->offset_root);
+      return (unsigned long) (revFlag ? BREV64(x): x);
+    }
+  }
+}
+
+long int ltt_event_get_long_int(ltt_event *e, ltt_field *f)
+{
+  ltt_arch_size rSize = e->tracefile->trace_header->arch_size;
+  int revFlag = e->tracefile->my_arch_endian == 
+                e->tracefile->trace_header->arch_endian ? 0:1;
+
+  if( f->field_type->type_class != LTT_INT)
+    g_error("The type of the field is not long int\n");
+
+  if(rSize == LTT_LP32 || rSize == LTT_ILP32 ){
+    if(f->field_size != 4)
+      g_error("The type of the field is not long int: int32_t\n");
+    else{
+      int32_t x = *(int32_t *)(e->data + f->offset_root);
+      return (long) (revFlag ? BREV32(x) : x); 
+    }
+  }else if(rSize == LTT_LP64 || rSize == LTT_ILP64){
+    if(f->field_size != 8)
+      g_error("The type of the field is not long int: int64_t\n");
+    else{
+      int64_t x = *(int64_t *)(e->data + f->offset_root);
+      return (long) (revFlag ? BREV64(x): x);
+    }
+  }
+}
+
+float ltt_event_get_float(ltt_event *e, ltt_field *f)
+{
+  int revFlag = e->tracefile->my_arch_endian == 
+                e->tracefile->trace_header->arch_endian ? 0:1;
+
+  if(f->field_type->type_class != LTT_FLOAT || 
+     (f->field_type->type_class == LTT_FLOAT && f->field_size != 4))
+    g_error("The type of the field is not float\n");
+
+  if(revFlag == 0) return *(float *)(e->data + f->offset_root);
+  else{
+    uint32_t aInt;
+    memcpy((void*)&aInt, e->data + f->offset_root, 4);
+    aInt = ___swab32(aInt);
+    return *((float*)&aInt);
+  }
+}
+
+double ltt_event_get_double(ltt_event *e, ltt_field *f)
+{
+  int revFlag = e->tracefile->my_arch_endian == 
+                e->tracefile->trace_header->arch_endian ? 0:1;
+
+  if(f->field_type->type_class != LTT_FLOAT || 
+     (f->field_type->type_class == LTT_FLOAT && f->field_size != 8))
+    g_error("The type of the field is not double\n");
+
+  if(revFlag == 0) return *(double *)(e->data + f->offset_root);
+  else{
+    uint64_t aInt;
+    memcpy((void*)&aInt, e->data + f->offset_root, 8);
+    aInt = ___swab64(aInt);
+    return *((double *)&aInt);
+  }
+}
+
+/*****************************************************************************
+ * The string obtained is only valid until the next read from
+ * the same tracefile. ????
+ ****************************************************************************/
+
+char *ltt_event_get_string(ltt_event *e, ltt_field *f)
+{
+  if(f->field_type->type_class != LTT_STRING)
+    g_error("The field contains no string\n");
+  return (char*)g_strdup((char*)(e->data + f->offset_root));
+}
diff --git a/ltt/branches/poly/ltt/facility.c b/ltt/branches/poly/ltt/facility.c
new file mode 100644 (file)
index 0000000..ad489ca
--- /dev/null
@@ -0,0 +1,497 @@
+#include <stdlib.h> 
+#include <string.h>
+#include <stdio.h>
+
+#include "LTTTypes.h"  
+#include "parser.h"
+#include <ltt/facility.h>
+
+/* search for the (named) type in the table, if it does not exist
+   create a new one */
+ltt_type * lookup_named_type(ltt_facility *fac, type_descriptor * td);
+
+/* construct directed acyclic graph for types, and tree for fields */
+void constructTypeAndFields(ltt_facility * fac,type_descriptor * td, 
+                            ltt_field * fld);
+
+/* generate the facility according to the events belongin to it */
+void generateFacility(ltt_facility * facility, char * pathname, 
+                      ltt_checksum checksum, sequence * events);
+
+/* functions to release the memory occupied by a facility */
+void freeFacility(ltt_facility * facility);
+void freeEventtype(ltt_eventtype * evType);
+void freeAllNamedTypes(table * named_types);
+void freeAllUnamedTypes(sequence * unnamed_types);
+void freeAllFields(sequence * all_fields);
+void freeLttType(ltt_type * type);
+void freeLttField(ltt_field * fld);
+
+
+/*****************************************************************************
+ *Function name
+ *    ltt_facility_open       : open a facility
+ *Input params
+ *    pathname                : the path name of the facility   
+ *    c                       : checksum of the facility registered in kernal
+ *Return value
+ *    ltt_facility*           : return a ltt_facility
+ ****************************************************************************/
+
+ltt_facility * ltt_facility_open(char * pathname, ltt_checksum c)
+{
+  char *token;
+  parse_file in;
+  char buffer[BUFFER_SIZE];
+  ltt_checksum checksum;
+  event *ev;
+  sequence  events;
+  table namedTypes;
+  sequence unnamedTypes;
+  ltt_facility * aFacility = NULL;
+
+  sequence_init(&events);
+  table_init(&namedTypes);
+  sequence_init(&unnamedTypes);
+
+  in.buffer = buffer;
+  in.lineno = 0;
+  in.error = error_callback;
+  in.name = appendString(pathname,".event");
+
+  in.fp = fopen(in.name, "r");
+  if(!in.fp )g_error("cannot open input file: %s\n", in.name);
+  while(1){
+    token = getToken(&in);
+    if(in.type == ENDFILE) break;
+    
+    if(strcmp("event",token) == 0) {
+      ev = g_new(event,1);
+      sequence_push(&events,ev);
+      parseEvent(&in,ev, &unnamedTypes, &namedTypes);
+    }
+    else if(strcmp("type",token) == 0) {
+      parseTypeDefinition(&in, &unnamedTypes, &namedTypes);
+    }
+    else g_error("event or type token expected\n");
+  }
+  
+  fclose(in.fp);
+
+  checkNamedTypesImplemented(&namedTypes);
+
+  generateChecksum(pathname, &checksum, &events);
+
+  //yxx disable during the test
+  aFacility = g_new(ltt_facility,1);    
+  generateFacility(aFacility, pathname, checksum, &events);
+/*
+  if(checksum == c){
+    aFacility = g_new(ltt_facility,1);    
+    generateFacility(aFacility, pathname, checksum, &events);
+  }else{
+    g_error("local facility is different from the one registered in the kernel");
+  }
+*/
+
+  free(in.name);
+  freeEvents(&events);
+  sequence_dispose(&events);
+  freeNamedType(&namedTypes);
+  table_dispose(&namedTypes);
+  freeTypes(&unnamedTypes);
+  sequence_dispose(&unnamedTypes);
+
+  return aFacility;
+}
+
+
+/*****************************************************************************
+ *Function name
+ *    generateFacility    : generate facility, internal function
+ *Input params 
+ *    facility            : facilty structure
+ *    facName             : facility name
+ *    checksum            : checksum of the facility          
+ *    events              : sequence of events belonging to the facility
+ ****************************************************************************/
+
+void generateFacility(ltt_facility * facility, char * pathname, 
+                      ltt_checksum checksum, sequence * events)
+{
+  char * facilityName;
+  int i;
+  ltt_eventtype * evType;
+  ltt_field * field;
+  ltt_type * type;
+
+  //get the facility name (strip any leading directory) 
+  facilityName = strrchr(pathname,'/');
+  if(facilityName) facilityName++;    
+  else facilityName = pathname;
+  
+  facility->name = g_strdup(facilityName);
+  facility->event_number = events->position;
+  facility->checksum = checksum;
+  facility->usage_count = 0;
+  
+  //initialize inner structures
+  facility->events = g_new(ltt_eventtype*,facility->event_number); 
+  sequence_init(&(facility->all_fields));
+  sequence_init(&(facility->all_unnamed_types));
+  table_init(&(facility->all_named_types));
+
+  //for each event, construct field tree and type graph
+  for(i=0;i<events->position;i++){
+    evType = g_new(ltt_eventtype,1);
+    facility->events[i] = evType;
+
+    evType->name = g_strdup(((event*)(events->array[i]))->name);
+    evType->description=g_strdup(((event*)(events->array[i]))->description);
+    
+    field = g_new(ltt_field, 1);
+    sequence_push(&(facility->all_fields), field);
+    evType->root_field = field;
+    evType->facility = facility;
+    evType->index = i;
+
+    field->field_pos = 0;
+    type = lookup_named_type(facility,((event*)(events->array[i]))->type);
+    field->field_type = type;
+    field->offset_root = 0;
+    field->fixed_root = 1;
+    field->offset_parent = 0;
+    field->fixed_parent = 1;
+    //    field->base_address = NULL;
+    field->field_size  = 0;
+    field->field_fixed = -1;
+    field->parent = NULL;
+    field->child = NULL;
+    field->current_element = 0;
+
+    //construct field tree and type graph
+    constructTypeAndFields(facility,((event*)(events->array[i]))->type,field);
+  }  
+}
+
+
+/*****************************************************************************
+ *Function name
+ *    constructTypeAndFields : construct field tree and type graph,
+ *                             internal recursion function
+ *Input params 
+ *    fac                    : facility struct
+ *    td                     : type descriptor
+ *    root_field             : root field of the event
+ ****************************************************************************/
+
+void constructTypeAndFields(ltt_facility * fac,type_descriptor * td, 
+                            ltt_field * fld)
+{
+  int i;
+  type_descriptor * tmpTd;
+
+  //  if(td->type == LTT_STRING || td->type == LTT_SEQUENCE)
+  //    fld->field_size = 0;
+  //  else fld->field_size = -1;
+
+  if(td->type == LTT_ENUM){
+    fld->field_type->element_number = td->labels.position;
+    fld->field_type->enum_strings = g_new(char*,td->labels.position);
+    for(i=0;i<td->labels.position;i++){
+      fld->field_type->enum_strings[i] 
+                          = g_strdup(((char*)(td->labels.array[i])));
+    }
+  }else if(td->type == LTT_ARRAY || td->type == LTT_SEQUENCE){
+    if(td->type == LTT_ARRAY)
+      fld->field_type->element_number = (unsigned)td->size;
+    fld->field_type->element_type = g_new(ltt_type*,1);
+    tmpTd = td->nested_type;
+    fld->field_type->element_type[0] = lookup_named_type(fac, tmpTd);
+    fld->child = g_new(ltt_field*, 1);
+    fld->child[0] = g_new(ltt_field, 1);
+    sequence_push(&(fac->all_fields), fld->child[0]);
+    
+    fld->child[0]->field_pos = 0;
+    fld->child[0]->field_type = fld->field_type->element_type[0];
+    fld->child[0]->offset_root = fld->offset_root;
+    fld->child[0]->fixed_root = fld->fixed_root;
+    fld->child[0]->offset_parent = 0;
+    fld->child[0]->fixed_parent = 1;
+    //    fld->child[0]->base_address = NULL;
+    fld->child[0]->field_size  = 0;
+    fld->child[0]->field_fixed = -1;
+    fld->child[0]->parent = fld;
+    fld->child[0]->child = NULL;
+    fld->child[0]->current_element = 0;
+    constructTypeAndFields(fac, tmpTd, fld->child[0]);
+  }else if(td->type == LTT_STRUCT){
+    fld->field_type->element_number = td->fields.position;
+    fld->field_type->element_type = g_new(ltt_type*, td->fields.position);
+    fld->child = g_new(ltt_field*, td->fields.position);      
+    for(i=0;i<td->fields.position;i++){
+      tmpTd = ((field*)(td->fields.array[i]))->type;
+      fld->field_type->element_type[i] = lookup_named_type(fac, tmpTd);
+      fld->child[i] = g_new(ltt_field,1); 
+      sequence_push(&(fac->all_fields), fld->child[i]);
+
+      fld->child[i]->field_pos = i;
+      fld->child[i]->field_type = fld->field_type->element_type[i]; 
+      fld->child[i]->field_type->element_name 
+                      = g_strdup(((field*)(td->fields.array[i]))->name);
+      fld->child[i]->offset_root = -1;
+      fld->child[i]->fixed_root = -1;
+      fld->child[i]->offset_parent = -1;
+      fld->child[i]->fixed_parent = -1;
+      //      fld->child[i]->base_address = NULL;
+      fld->child[i]->field_size  = 0;
+      fld->child[i]->field_fixed = -1;
+      fld->child[i]->parent = fld;
+      fld->child[i]->child = NULL;
+      fld->child[i]->current_element = 0;
+      constructTypeAndFields(fac, tmpTd, fld->child[i]);
+    }    
+  }
+}
+
+
+/*****************************************************************************
+ *Function name
+ *    lookup_named_type: search named type in the table
+ *                       internal function
+ *Input params 
+ *    fac              : facility struct
+ *    td               : type descriptor
+ *Return value    
+ *                     : either find the named type, or create a new ltt_type
+ ****************************************************************************/
+
+ltt_type * lookup_named_type(ltt_facility *fac, type_descriptor * td)
+{
+  ltt_type * lttType = NULL;
+  int i;
+  char * name;
+  if(td->type_name){
+    for(i=0;i<fac->all_named_types.keys.position;i++){
+      name = (char *)(fac->all_named_types.keys.array[i]);
+      if(strcmp(name, td->type_name)==0){
+       lttType = (ltt_type*)(fac->all_named_types.values.array[i]);
+       break;
+      }
+    }
+  }
+  
+  if(!lttType){
+    lttType = g_new(ltt_type,1);
+    lttType->type_class = td->type;
+    if(td->fmt) lttType->fmt = g_strdup(td->fmt);
+    else lttType->fmt = NULL;
+    lttType->size = td->size;
+    lttType->enum_strings = NULL;
+    lttType->element_type = NULL;
+    lttType->element_number = 0;
+    if(td->type_name){
+      name = g_strdup(td->type_name);
+      table_insert(&(fac->all_named_types),name,lttType);
+      lttType->element_name = name;
+    }
+    else{
+      sequence_push(&(fac->all_unnamed_types), lttType);
+      lttType->element_name = NULL;
+    }
+  }
+
+  return lttType;
+}
+
+
+/*****************************************************************************
+ *Function name
+ *    ltt_facility_close      : close a facility, decrease its usage count,
+ *                              if usage count = 0, release the memory
+ *Input params
+ *    f                       : facility that will be closed
+ *Return value
+ *    int                     : usage count ?? status
+ ****************************************************************************/
+
+int ltt_facility_close(ltt_facility *f)
+{
+  //  f->usage_count--;
+  if(f->usage_count > 0) return f->usage_count;
+  
+  //release the memory it occupied
+  freeFacility(f);
+
+  return 0;
+}
+
+/*****************************************************************************
+ * Functions to release the memory occupied by the facility
+ ****************************************************************************/
+
+void freeFacility(ltt_facility * fac)
+{
+  int i;
+  g_free(fac->name);  //free facility name
+
+  //free event types
+  for(i=0;i<fac->event_number;i++){
+    freeEventtype(fac->events[i]);
+  }
+
+  //free all named types
+  freeAllNamedTypes(&(fac->all_named_types));
+
+  //free all unnamed types
+  freeAllUnamedTypes(&(fac->all_unnamed_types));
+
+  //free all fields
+  freeAllFields(&(fac->all_fields));
+
+  //free the facility itself
+  g_free(fac);
+}
+
+void freeEventtype(ltt_eventtype * evType)
+{
+  g_free(evType->name);
+  if(evType->description)
+    g_free(evType->description); 
+  g_free(evType);
+}
+
+void freeAllNamedTypes(table * named_types)
+{
+  int i;
+  for(i=0;i<named_types->keys.position;i++){
+    //free the name of the type
+    g_free((char*)(named_types->keys.array[i]));
+    
+    //free type
+    freeLttType((ltt_type*)(named_types->values.array[i]));
+  }
+  table_dispose(named_types);
+}
+
+void freeAllUnamedTypes(sequence * unnamed_types)
+{
+  int i;
+  for(i=0;i<unnamed_types->position;i++){
+    freeLttType((ltt_type*)(unnamed_types->array[i]));
+  }
+  sequence_dispose(unnamed_types);
+}
+
+void freeAllFields(sequence * all_fields)
+{
+  int i;
+  for(i=0;i<all_fields->position;i++){
+    freeLttField((ltt_field*)(all_fields->array[i]));
+  }
+  sequence_dispose(all_fields);
+}
+
+void freeLttType(ltt_type * type)
+{
+  if(type->element_name)
+    g_free(type->element_name);
+  if(type->fmt)
+    g_free(type->fmt);
+  if(type->enum_strings)
+    g_free(type->enum_strings);
+  if(type->element_type)
+    g_free(type->element_type);
+  g_free(type);
+}
+
+void freeLttField(ltt_field * fld)
+{  
+  if(fld->child)
+    g_free(fld->child);
+  g_free(fld);
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_facility_name       : obtain the facility's name
+ *Input params
+ *    f                       : the facility that will be closed
+ *Return value
+ *    char *                  : the facility's name
+ ****************************************************************************/
+
+char *ltt_facility_name(ltt_facility *f)
+{
+  return f->name;
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_facility_checksum   : obtain the facility's checksum
+ *Input params
+ *    f                       : the facility that will be closed
+ *Return value
+ *    ltt_checksum            : the checksum of the facility 
+ ****************************************************************************/
+
+ltt_checksum ltt_facility_checksum(ltt_facility *f)
+{
+  return f->checksum;
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_facility_eventtype_number: obtain the number of the event types 
+ *Input params
+ *    f                            : the facility that will be closed
+ *Return value
+ *    unsigned                     : the number of the event types 
+ ****************************************************************************/
+
+unsigned ltt_facility_eventtype_number(ltt_facility *f)
+{
+  return (unsigned)(f->event_number);
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_facility_eventtype_get: obtain the event type according to event id
+ *                                from 0 to event_number - 1
+ *Input params
+ *    f                         : the facility that will be closed
+ *Return value
+ *    ltt_eventtype *           : the event type required  
+ ****************************************************************************/
+
+ltt_eventtype *ltt_facility_eventtype_get(ltt_facility *f, unsigned i)
+{
+  return f->events[i];
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_facility_eventtype_get_by_name
+ *                     : obtain the event type according to event name
+ *                       event name is unique in the facility
+ *Input params
+ *    f                : the facility that will be closed
+ *    name             : the name of the event
+ *Return value
+ *    ltt_eventtype *  : the event type required  
+ ****************************************************************************/
+
+ltt_eventtype *ltt_facility_eventtype_get_by_name(ltt_facility *f, char *name)
+{
+  int i;
+  ltt_eventtype * ev;
+  for(i=0;i<f->event_number;i++){
+    ev = f->events[i];
+    if(strcmp(ev->name, name) == 0)break;      
+  }
+
+  if(i==f->event_number) return NULL;
+  else return ev;
+}
+
diff --git a/ltt/branches/poly/ltt/parser.c b/ltt/branches/poly/ltt/parser.c
new file mode 100644 (file)
index 0000000..2851188
--- /dev/null
@@ -0,0 +1,985 @@
+/*
+
+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
+   it under the terms of the GNU General Public License as published by
+the Free Software Foundation; version 2 of the License.
+
+This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+*/
+
+/* This program reads the ".event" event definitions input files 
+   specified as command line arguments and generates corresponding
+   ".c" and ".h" files required to trace such events in the kernel.
+   The program uses a very simple tokenizer, called from a hand written
+   recursive descent parser to fill a data structure describing the events.
+   The result is a sequence of events definitions which refer to type
+   definitions.
+
+   A table of named types is maintained to allow refering to types by name
+   when the same type is used at several places. Finally a sequence of
+   all types is maintained to facilitate the freeing of all type 
+   information when the processing of an ".event" file is finished. */
+
+#include <stdlib.h> 
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <linux/errno.h>  
+
+
+#include "parser.h"
+
+
+/*****************************************************************************
+ *Function name
+ *    getSize    : translate from string to integer
+ *Input params 
+ *    in         : input file handle
+ *Return values  
+ *    size                           
+ *****************************************************************************/
+
+int getSize(parse_file *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;
+  }
+  in->error(in,"incorrect size specification");
+  return -1;
+}
+
+/*****************************************************************************
+ *Function name
+ *    error_callback  : print out error info
+ *Input params
+ *    in              : input file handle
+ *    msg             : message to be printed                  
+ ****************************************************************************/
+
+void error_callback(parse_file *in, char *msg)
+{
+  if(in)
+    printf("Error in file %s, line %d: %s\n", in->name, in->lineno, msg);
+  else
+    printf("%s\n",msg);
+  exit(1);
+}
+
+/*****************************************************************************
+ *Function name
+ *    memAlloc  : allocate memory                    
+ *Input params 
+ *    size      : required memory size               
+ *return value 
+ *    void *    : pointer to allocate memory or NULL 
+ ****************************************************************************/
+
+void * memAlloc(int size)
+{
+  void *addr = malloc(size);
+  if(!addr){
+    printf("Failed to allocate memory");    
+    exit(1);
+  }
+  return addr;   
+}
+
+/*****************************************************************************
+ *Function name
+ *    allocAndCopy : allocate memory and initialize it  
+ *Input params 
+ *    str          : string to be put in memory         
+ *return value 
+ *    char *       : pointer to allocate memory or NULL
+ ****************************************************************************/
+
+char *allocAndCopy(char *str)
+{
+  char *addr = (char *)memAlloc(strlen(str)+1);
+  strcpy(addr,str);
+  return addr;
+}
+
+
+/*****************************************************************************
+ *Function name
+ *    parseEvent    : generate event from event definition 
+ *Input params 
+ *    in            : input file handle          
+ *    ev            : new event                              
+ *Output params    
+ *    ev            : new event (parameters are passed to it)   
+ ****************************************************************************/
+
+void parseEvent(parse_file *in, event * ev, sequence * unnamed_types, 
+               table * named_types) 
+{
+  char *token;
+  type_descriptor *t;
+
+  getLParenthesis(in);
+  token = getName(in);
+  ev->name = allocAndCopy(token);
+  getComa(in);
+
+  token = getQuotedString(in);
+  ev->description = allocAndCopy(token);
+  
+  token = getToken(in); //token either is a ',' or a ')'
+  if(in->type == COMA) token = getName(in);
+  ungetToken(in);
+
+  /* We have a possibly empty list of fields, containing struct implied */
+  if((in->type == NAME && strcmp(token,"field") == 0) || 
+      in->type == RPARENTHESIS) {
+    /* Insert an unnamed struct type */
+    t = (type_descriptor *)memAlloc(sizeof(type_descriptor));
+    t->type_name = NULL;
+    t->type = STRUCT;
+    t->fmt = NULL;
+    if(in->type == NAME) parseFields(in,t, unnamed_types, named_types);
+    else if(in->type == RPARENTHESIS) sequence_init(&(t->fields));      
+    sequence_push(unnamed_types,t);
+    ev->type = t;
+  }
+
+  /* Or a complete type declaration but it must be a struct */
+  else if(in->type == NAME){
+    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 struct type");
+
+  getRParenthesis(in);
+  getSemiColon(in);
+}
+
+/*****************************************************************************
+ *Function name
+ *    parseField  : get field infomation from buffer 
+ *Input params 
+ *    in          : input file handle
+ *    t           : type descriptor
+ ****************************************************************************/
+
+void parseFields(parse_file *in, type_descriptor *t, sequence * unnamed_types,
+                table * named_types) 
+{
+  char * token;
+  field *f;
+
+  sequence_init(&(t->fields));
+
+  token = getToken(in);
+  while(in->type == NAME && strcmp(token,"field") == 0) {
+    f = (field *)memAlloc(sizeof(field));
+    sequence_push(&(t->fields),f);
+
+    getLParenthesis(in);
+    f->name = (char *)allocAndCopy(getName(in));
+    getComa(in);
+    f->description = (char *)allocAndCopy(getQuotedString(in));
+    getComa(in);
+    f->type = parseType(in,NULL, unnamed_types, named_types);
+    getRParenthesis(in);
+    
+    token = getToken(in);
+    if(in->type == COMA) token = getName(in);
+    else ungetToken(in); // no more fields, it must be a ')'
+  }
+
+  if(in->type == NAME && strcmp(token,"field") != 0)
+    in->error(in,"not a field");
+}
+
+
+/*****************************************************************************
+ *Function name
+ *    parseType      : get type information, type can be : 
+ *                     Primitive:
+ *                        int(size,fmt); uint(size,fmt); float(size,fmt); 
+ *                        string(fmt); enum(size,fmt,(label1,label2...))
+ *                     Compound:
+ *                        array(arraySize, type); sequence(lengthSize,type)
+ *                       struct(field(name,type,description)...)
+ *                     type name:
+ *                        type(name,type)
+ *Input params 
+ *    in               : input file handle
+ *    inType           : a type descriptor          
+ *Return values  
+ *    type_descriptor* : a type descriptor             
+ ****************************************************************************/
+
+type_descriptor *parseType(parse_file *in, type_descriptor *inType, 
+                          sequence * unnamed_types, table * named_types) 
+{
+  char *token, *car;
+  type_descriptor *t;
+
+  if(inType == NULL) {
+    t = (type_descriptor *) memAlloc(sizeof(type_descriptor));
+    t->type_name = NULL;
+    t->type = NONE;
+    t->fmt = NULL;
+    sequence_push(unnamed_types,t);
+  }
+  else t = inType;
+
+  token = getName(in);
+
+  if(strcmp(token,"struct") == 0) {
+    t->type = STRUCT;
+    getLParenthesis(in);
+    parseFields(in,t, unnamed_types, named_types);
+    getRParenthesis(in);
+  }
+  else if(strcmp(token,"array") == 0) {
+    t->type = ARRAY;
+    getLParenthesis(in);
+    t->size = getNumber(in);
+    getComa(in);
+    t->nested_type = parseType(in,NULL, unnamed_types, named_types);
+    getRParenthesis(in);
+  }
+  else if(strcmp(token,"sequence") == 0) {
+    t->type = SEQUENCE;
+    getLParenthesis(in);
+    t->size = getSize(in);
+    getComa(in);
+    t->nested_type = parseType(in,NULL, unnamed_types, named_types);
+    getRParenthesis(in);
+  }
+  else if(strcmp(token,"enum") == 0) {
+    t->type = ENUM;
+    sequence_init(&(t->labels));
+    getLParenthesis(in);
+    t->size = getSize(in);
+    getComa(in);
+    token = getToken(in);
+    if(in->type == QUOTEDSTRING){
+      t->fmt = allocAndCopy(token);
+      getComa(in);
+    }else ungetToken(in);
+    getLParenthesis(in);
+
+    token = getToken(in);
+    while(in->type != RPARENTHESIS) {
+      if(in->type != NAME) in->error(in,"Name token was expected");
+      car = allocAndCopy(token);
+      token = getToken(in);
+      if(in->type == COMA){
+       sequence_push(&(t->labels),allocAndCopy(car));
+       token = getName(in);
+      }else if(in->type == EQUAL){ //label followed by '=' and a number, e.x. label1 = 1,
+       car = appendString(car, token);
+       token = getToken(in);
+       if(in->type != NUMBER) in->error(in,"Number token was expected");
+       car = appendString(car, token);
+       sequence_push(&(t->labels),allocAndCopy(car));  
+       token = getToken(in);
+       if(in->type == COMA) token = getName(in);
+       else ungetToken(in);
+      }else{
+       sequence_push(&(t->labels),allocAndCopy(car));
+       ungetToken(in);
+      }
+    }  
+    getRParenthesis(in);
+    getRParenthesis(in);
+  }
+  else if(strcmp(token,"int") == 0) {
+    t->type = INT;
+    getLParenthesis(in);
+    t->size = getSize(in);
+    token = getToken(in);
+    if(in->type == COMA) {
+      token = getQuotedString(in);
+      t->fmt = allocAndCopy(token);
+    }
+    else ungetToken(in);
+    getRParenthesis(in);
+  }
+  else if(strcmp(token,"uint") == 0) {
+    t->type = UINT;
+    getLParenthesis(in);
+    t->size = getSize(in);
+    token = getToken(in);
+    if(in->type == COMA) {
+      token = getQuotedString(in);
+      t->fmt = allocAndCopy(token);
+    }
+    else ungetToken(in);
+    getRParenthesis(in);
+  }
+  else if(strcmp(token,"float") == 0) {
+    t->type = FLOAT;
+    getLParenthesis(in);
+    t->size = getSize(in);
+    token = getToken(in);
+    if(in->type == COMA) {
+      token = getQuotedString(in);
+      t->fmt = allocAndCopy(token);
+    }
+    else ungetToken(in);
+    getRParenthesis(in);
+  }
+  else if(strcmp(token,"string") == 0) {
+    t->type = STRING;
+    getLParenthesis(in);
+    token = getToken(in);
+    if(in->type == QUOTEDSTRING) t->fmt = allocAndCopy(token);
+    else ungetToken(in);
+    getRParenthesis(in);
+  }
+  else {
+    /* 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);
+      return(find_named_type(token, named_types));
+    }
+  }
+
+  return t;
+}    
+
+/*****************************************************************************
+ *Function name
+ *    find_named_type     : find a named type from hash table 
+ *Input params 
+ *    name                : type name          
+ *Return values  
+ *    type_descriptor *   : a type descriptor                       
+ *****************************************************************************/
+
+type_descriptor * find_named_type(char *name, table * named_types)
+{ 
+  type_descriptor *t;
+
+  t = table_find(named_types,name);
+  if(t == NULL) {
+    t = (type_descriptor *)memAlloc(sizeof(type_descriptor));
+    t->type_name = allocAndCopy(name);
+    t->type = NONE;
+    t->fmt = NULL;
+    table_insert(named_types,allocAndCopy(name),t);
+  }
+  return t;
+}  
+
+/*****************************************************************************
+ *Function name
+ *    parseTypeDefinition : get type information from type definition 
+ *Input params 
+ *    in                  : input file handle          
+ *****************************************************************************/
+
+void parseTypeDefinition(parse_file * in, sequence * unnamed_types,
+                        table * named_types)
+{
+  char *token;
+  type_descriptor *t;
+
+  getLParenthesis(in);
+  token = getName(in);
+  t = find_named_type(token, named_types);
+  getComa(in);
+
+  if(t->type != NONE) in->error(in,"redefinition of named type");
+  parseType(in,t, unnamed_types, named_types);
+
+  getRParenthesis(in);
+  getSemiColon(in);
+}
+
+/**************************************************************************
+ * Function :
+ *    getComa, getName, getNumber, getLParenthesis, getRParenthesis, getEqual
+ * Description :
+ *    Read a token from the input file, check its type, return it scontent.
+ *
+ * Parameters :
+ *    in , input file handle.
+ *
+ * Return values :
+ *    address of token content.
+ *
+ **************************************************************************/
+
+char *getName(parse_file * in) 
+{
+  char *token;
+
+  token = getToken(in);
+  if(in->type != NAME) in->error(in,"Name token was expected");
+  return token;
+}
+
+int getNumber(parse_file * in) 
+{
+  char *token;
+
+  token = getToken(in);
+  if(in->type != NUMBER) in->error(in, "Number token was expected");
+  return atoi(token);
+}
+
+char *getComa(parse_file * in) 
+{
+  char *token;
+
+  token = getToken(in);
+  if(in->type != COMA) in->error(in, "Coma token was expected");
+  return token;
+}
+
+char *getLParenthesis(parse_file * in) 
+{
+  char *token;
+
+  token = getToken(in);
+  if(in->type != LPARENTHESIS) in->error(in, "Left parenthesis was expected");
+  return token;
+}
+
+char *getRParenthesis(parse_file * in) 
+{
+  char *token;
+
+  token = getToken(in);
+  if(in->type != RPARENTHESIS) in->error(in, "Right parenthesis was expected");
+  return token;
+}
+
+char *getQuotedString(parse_file * in) 
+{
+  char *token;
+
+  token = getToken(in);
+  if(in->type != QUOTEDSTRING) in->error(in, "quoted string was expected");
+  return token;
+}
+
+char * getSemiColon(parse_file *in)
+{
+  char *token;
+
+  token = getToken(in);
+  if(in->type != SEMICOLON) in->error(in, "semicolon was expected");
+  return token;
+}
+
+char * getEqual(parse_file *in)
+{
+  char *token;
+
+  token = getToken(in);
+  if(in->type != EQUAL) in->error(in, "equal was expected");
+  return token;
+}
+
+/******************************************************************
+ * Function :
+ *    getToken, ungetToken
+ * Description :
+ *    Read a token from the input file and return its type and content.
+ *    Line numbers are accounted for and whitespace/comments are skipped.
+ *
+ * Parameters :
+ *    in, input file handle.
+ *
+ * Return values :
+ *    address of token content.
+ *
+ ******************************************************************/
+
+void ungetToken(parse_file * in)
+{
+  in->unget = 1;
+}
+
+char *getToken(parse_file * in)
+{
+  FILE *fp = in->fp;
+  char car, car1;
+  int pos = 0, escaped;
+
+  if(in->unget == 1) {
+    in->unget = 0;
+    return in->buffer;
+  }
+
+  /* skip whitespace and comments */
+
+  while((car = getc(fp)) != EOF) {
+    if(car == '/') {
+      car1 = getc(fp); 
+      if(car1 == '*') skipComment(in);
+      else if(car1 == '/') skipEOL(in);
+      else { 
+        car1 = ungetc(car1,fp);
+        break;
+      }
+    }
+    else if(car == '\n') in->lineno++;
+    else if(!isspace(car)) break;
+  }
+
+  switch(car) {
+    case EOF:
+      in->type = ENDFILE;
+      break;
+    case ',':
+      in->type = COMA;
+      in->buffer[pos] = car;
+      pos++;
+      break;
+    case '(':
+      in->type = LPARENTHESIS;
+      in->buffer[pos] = car;
+      pos++;
+      break;
+    case ')':
+      in->type = RPARENTHESIS;
+      in->buffer[pos] = car;
+      pos++;
+      break;
+    case ';':
+      in->type = SEMICOLON;
+      in->buffer[pos] = car;
+      pos++;
+      break;
+    case '=':
+      in->type = EQUAL;
+      in->buffer[pos] = car;
+      pos++;
+      break;
+    case '"':
+      escaped = 0;
+      while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) {
+        if(car == '\\' && escaped == 0) {
+         in->buffer[pos] = car;
+         pos++;
+          escaped = 1;
+          continue;
+        }
+        if(car == '"' && escaped == 0) break;
+        if(car == '\n' && escaped == 0) {
+          in->error(in, "non escaped newline inside quoted string");
+        }
+        if(car == '\n') in->lineno++;
+        in->buffer[pos] = car;
+        pos++;
+        escaped = 0;
+      }
+      if(car == EOF) in->error(in,"no ending quotemark");
+      if(pos == BUFFER_SIZE) in->error(in, "quoted string token too large");
+      in->type = QUOTEDSTRING;
+      break;
+    default:
+      if(isdigit(car)) {
+        in->buffer[pos] = car;
+        pos++;
+        while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) {
+          if(!isdigit(car)) {
+            ungetc(car,fp);
+            break;
+          }
+          in->buffer[pos] = car;
+          pos++;
+        }
+       if(car == EOF) ungetc(car,fp);
+        if(pos == BUFFER_SIZE) in->error(in, "number token too large");
+        in->type = NUMBER;
+      }    
+      else if(isalpha(car)) {
+        in->buffer[0] = car;
+        pos = 1;
+        while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) {
+          if(!isalnum(car)) {
+            ungetc(car,fp);
+            break;
+          }
+          in->buffer[pos] = car;
+          pos++;
+        }
+       if(car == EOF) ungetc(car,fp);
+        if(pos == BUFFER_SIZE) in->error(in, "name token too large");
+        in->type = NAME;
+      }
+      else in->error(in, "invalid character, unrecognized token");
+  }
+  in->buffer[pos] = 0;
+  return in->buffer;
+}
+
+void skipComment(parse_file * in)
+{
+  char car;
+  while((car = getc(in->fp)) != EOF) {
+    if(car == '\n') in->lineno++;
+    else if(car == '*') {
+      car = getc(in->fp);
+      if(car ==EOF) break;
+      if(car == '/') return;
+      ungetc(car,in->fp);
+    }
+  }
+  if(car == EOF) in->error(in,"comment begining with '/*' has no ending '*/'");
+}
+
+void skipEOL(parse_file * in)
+{
+  char car;
+  while((car = getc(in->fp)) != EOF) {
+    if(car == '\n') {
+      ungetc(car,in->fp);
+      break;
+    }
+  }
+  if(car == EOF)ungetc(car, in->fp);
+}
+
+int isalpha(char c)
+{
+  int i,j;
+  if(c == '_')return 1;
+  i = c - 'a';
+  j = c - 'A';
+  if((i>=0 && i<26) || (j>=0 && j<26)) return 1;
+  return 0;
+}
+
+int isalnum(char c)
+{
+  return (isalpha(c) || isdigit(c));
+}
+
+/*****************************************************************************
+ *Function name
+ *    checkNamedTypesImplemented : check if all named types have definition
+ ****************************************************************************/
+
+void checkNamedTypesImplemented(table * named_types)
+{
+  type_descriptor *t;
+  int pos;
+  char str[256];
+
+  for(pos = 0 ; pos < named_types->values.position; pos++) {
+    t = (type_descriptor *) named_types->values.array[pos];
+    if(t->type == NONE){
+      sprintf(str,"named type '%s' has no definition",(char*)named_types->keys.array[pos]);
+      error_callback(NULL,str);   
+    }
+  }
+}
+
+
+/*****************************************************************************
+ *Function name
+ *    generateChecksum  : generate checksum for the facility
+ *Input Params
+ *    facName           : name of facility
+ *Output Params
+ *    checksum          : checksum for the facility
+ ****************************************************************************/
+
+void generateChecksum( char* facName, unsigned long * checksum, sequence * events)
+{
+  unsigned long crc ;
+  int pos, nestedStruct;
+  event * ev;
+  char str[256];
+
+  crc = crc32(facName);
+  for(pos = 0; pos < events->position; pos++){
+    ev = (event *)(events->array[pos]);
+    ev->nested = 0; //by default, event has no nested struct
+    crc = partial_crc32(ev->name,crc);    
+    nestedStruct = 0;
+    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,&nestedStruct);
+    if(nestedStruct ) ev->nested = 1;
+  }
+  *checksum = crc;
+}
+
+/*****************************************************************************
+ *Function name
+ *   getTypeChecksum    : generate checksum by type info
+ *Input Params
+ *    crc               : checksum generated so far
+ *    type              : type descriptor containing type info
+ *Return value          
+ *    unsigned long     : checksum 
+ *****************************************************************************/
+
+unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor * type,
+                             int * nestedStruct)
+{
+  unsigned long crc = aCrc;
+  char * str = NULL, buf[16];
+  int flag = 0, pos, max, min;
+  field * fld;
+  data_type dt;
+
+  switch(type->type){
+    case INT:
+      str = intOutputTypes[type->size];
+      break;
+    case UINT:
+      str = uintOutputTypes[type->size];
+      break;
+    case FLOAT:
+      str = floatOutputTypes[type->size];
+      break;
+    case STRING:
+      str = allocAndCopy("string");
+      flag = 1;
+      break;
+    case ENUM:
+      str = appendString("enum ", uintOutputTypes[type->size]);
+      flag = 1;
+      break;
+    case ARRAY:
+      sprintf(buf,"%d\0",type->size);
+      str = appendString("array ",buf);
+      flag = 1;
+      break;
+    case SEQUENCE:
+      sprintf(buf,"%d\0",type->size);
+      str = appendString("sequence ",buf);
+      flag = 1;
+      break;
+    case STRUCT:
+      str = allocAndCopy("struct");
+      flag = 1;
+      break;
+    default:
+      error_callback(NULL, "named type has no definition");
+      break;
+  }
+
+  crc = partial_crc32(str,crc);
+  if(flag) free(str);
+
+  if(type->fmt) crc = partial_crc32(type->fmt,crc);
+    
+  if(type->type == ARRAY || type->type == SEQUENCE){
+    dt = type->nested_type->type;
+    if(dt == ARRAY || dt == SEQUENCE || dt == STRUCT) *nestedStruct += 1;
+    crc = getTypeChecksum(crc,type->nested_type,nestedStruct);
+  }else if(type->type == STRUCT){
+    if(type->fields.position != 0){//not a empty struct
+      max = 0;      
+      for(pos =0; pos < type->fields.position; pos++){
+       min = 0;
+       fld = (field *) type->fields.array[pos];
+       crc = partial_crc32(fld->name,crc);
+       if(fld->type->type == STRUCT) min++;
+       crc = getTypeChecksum(crc, fld->type,&min);
+       if(min>max) max = min;
+      }
+      *nestedStruct += max;
+    }
+  }else if(type->type == ENUM){
+    for(pos = 0; pos < type->labels.position; pos++)
+      crc = partial_crc32((char*)type->labels.array[pos],crc);    
+  }
+
+  return crc;
+}
+
+
+/* Event type descriptors */
+void freeType(type_descriptor * tp)
+{
+  int pos2;
+  field *f;
+
+  if(tp->fmt != NULL) free(tp->fmt);
+  if(tp->type == ENUM) {
+    for(pos2 = 0; pos2 < tp->labels.position; pos2++) {
+      free(tp->labels.array[pos2]);
+    }
+    sequence_dispose(&(tp->labels));
+  }
+  if(tp->type == STRUCT) {
+    for(pos2 = 0; pos2 < tp->fields.position; pos2++) {
+      f = (field *) tp->fields.array[pos2];
+      free(f->name);
+      free(f->description);
+      free(f);
+    }
+    sequence_dispose(&(tp->fields));
+  }
+}
+
+void freeNamedType(table * t)
+{
+  int pos;
+  type_descriptor * td;
+
+  for(pos = 0 ; pos < t->keys.position; pos++) {
+    free((char *)t->keys.array[pos]);
+    td = (type_descriptor*)t->values.array[pos];
+    freeType(td);
+    free(td);
+  }
+}
+
+void freeTypes(sequence *t) 
+{
+  int pos, pos2;
+  type_descriptor *tp;
+  field *f;
+
+  for(pos = 0 ; pos < t->position; pos++) {
+    tp = (type_descriptor *)t->array[pos];
+    freeType(tp);
+    free(tp);
+  }
+}
+
+void freeEvents(sequence *t) 
+{
+  int pos;
+  event *ev;
+
+  for(pos = 0 ; pos < t->position; pos++) {
+    ev = (event *) t->array[pos];
+    free(ev->name);
+    free(ev->description);
+    free(ev);
+  }
+
+}
+
+
+/* Extensible array */
+
+void sequence_init(sequence *t) 
+{
+  t->size = 10;
+  t->position = 0;
+  t->array = (void **)memAlloc(t->size * sizeof(void *));
+}
+
+void sequence_dispose(sequence *t) 
+{
+  t->size = 0;
+  free(t->array);
+  t->array = NULL;
+}
+
+void sequence_push(sequence *t, void *elem) 
+{
+  void **tmp;
+
+  if(t->position >= t->size) {
+    tmp = t->array;
+    t->array = (void **)memAlloc(t->size * 2 * sizeof(void *));
+    memcpy(t->array, tmp, t->size * sizeof(void *));
+    t->size = t->size * 2;
+    free(tmp);
+  }
+  t->array[t->position] = elem;
+  t->position++;
+}
+
+void *sequence_pop(sequence *t) 
+{
+  return t->array[t->position--];
+}
+
+
+/* Hash table API, implementation is just linear search for now */
+
+void table_init(table *t) 
+{
+  sequence_init(&(t->keys));
+  sequence_init(&(t->values));
+}
+
+void table_dispose(table *t) 
+{
+  sequence_dispose(&(t->keys));
+  sequence_dispose(&(t->values));
+}
+
+void table_insert(table *t, char *key, void *value) 
+{
+  sequence_push(&(t->keys),key);
+  sequence_push(&(t->values),value);
+}
+
+void *table_find(table *t, char *key) 
+{
+  int pos;
+  for(pos = 0 ; pos < t->keys.position; pos++) {
+    if(strcmp((char *)key,(char *)t->keys.array[pos]) == 0)
+      return(t->values.array[pos]);
+  }
+  return NULL;
+}
+
+void table_insert_int(table *t, int *key, void *value)
+{
+  sequence_push(&(t->keys),key);
+  sequence_push(&(t->values),value);
+}
+
+void *table_find_int(table *t, int *key)
+{
+  int pos;
+  for(pos = 0 ; pos < t->keys.position; pos++) {
+    if(*key == *(int *)t->keys.array[pos])
+      return(t->values.array[pos]);
+  }
+  return NULL;
+}
+
+
+/* Concatenate strings */
+
+char *appendString(char *s, char *suffix) 
+{
+  char *tmp;
+
+  tmp = (char *)memAlloc(strlen(s) + strlen(suffix) + 1);
+  strcpy(tmp,s);
+  strcat(tmp,suffix);  
+  return tmp;
+}
+
+
diff --git a/ltt/branches/poly/ltt/parser.h b/ltt/branches/poly/ltt/parser.h
new file mode 100644 (file)
index 0000000..5e0c421
--- /dev/null
@@ -0,0 +1,189 @@
+#ifndef PARSER_H
+#define PARSER_H
+
+/* Extensible array container */
+
+typedef struct _sequence {
+  int size;
+  int position;
+  void **array;
+} sequence;
+
+void sequence_init(sequence *t);
+void sequence_dispose(sequence *t);
+void sequence_push(sequence *t, void *elem);
+void *sequence_pop(sequence *t);
+
+
+/* Hash table */
+
+typedef struct _table {
+  sequence keys;
+  sequence values;
+} table;
+
+void table_init(table *t);
+void table_dispose(table *t);
+void table_insert(table *t, char *key, void *value);
+void *table_find(table *t, char *key);
+void table_insert_int(table *t, int *key, void *value);
+void *table_find_int(table *t, int *key);
+
+
+/* Token types */
+
+typedef enum _token_type {
+  ENDFILE,
+  COMA,
+  LPARENTHESIS,
+  RPARENTHESIS,
+  SEMICOLON,
+  EQUAL,
+  QUOTEDSTRING,
+  NUMBER,
+  NAME
+} token_type;
+
+
+/* State associated with a file being parsed */
+typedef struct _parse_file {
+  char *name;
+  FILE * fp;
+  int lineno;
+  char *buffer;
+  token_type type; 
+  int unget;
+  void (*error) (struct _parse_file *, char *);
+} parse_file;
+
+void ungetToken(parse_file * in);
+char *getToken(parse_file *in);
+char *getComa(parse_file *in);
+char *getLParenthesis(parse_file *in);
+char *getRParenthesis(parse_file *in);
+char *getSemiColon(parse_file *in);
+char *getQuotedString(parse_file *in);
+char *getName(parse_file *in);
+int getNumber(parse_file *in);
+char * getEqual(parse_file *in);
+
+void skipComment(parse_file * in);
+void skipEOL(parse_file * in);
+int isalpha(char car);
+int isalnum(char car);
+
+/* Some constants */
+
+static const int BUFFER_SIZE = 1024;
+
+
+/* Events data types */
+
+typedef enum _data_type {
+  INT,
+  UINT,
+  FLOAT,
+  STRING,
+  ENUM,
+  ARRAY,
+  SEQUENCE,
+  STRUCT,
+  NONE
+} data_type;
+
+
+/* Event type descriptors */
+
+typedef struct _type_descriptor {
+  char * type_name; //used for named type
+  data_type type;
+  char *fmt;
+  int size;
+  sequence labels; // for enumeration
+  sequence fields; // for structure
+  struct _type_descriptor *nested_type; // for array and sequence 
+} type_descriptor;
+
+
+/* Fields within types */
+
+typedef struct _field{
+  char *name;
+  char *description;
+  type_descriptor *type;
+} field;
+
+
+/* Events definitions */
+
+typedef struct _event {  
+  char *name;
+  char *description;
+  type_descriptor *type; 
+  int nested;
+} event;
+
+int getSize(parse_file *in);
+unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor * type, int * nestedStruct);
+
+void parseEvent(parse_file *in, event *ev, sequence * unnamed_types, table * named_types);
+void parseTypeDefinition(parse_file *in, sequence * unnamed_types, table * named_types);
+type_descriptor *parseType(parse_file *in, type_descriptor *t, sequence * unnamed_types, table * named_types);
+void parseFields(parse_file *in, type_descriptor *t, sequence * unnamed_types, table * named_types);
+void checkNamedTypesImplemented(table * namedTypes);
+type_descriptor * find_named_type(char *name, table * named_types);
+void generateChecksum(char * facName, unsigned long * checksum, sequence * events);
+
+
+
+static char *intOutputTypes[] = {
+  "int8_t", "int16_t", "int32_t", "int64_t", "short int", "int", "long int" };
+
+static char *uintOutputTypes[] = {
+  "uint8_t", "uint16_t", "uint32_t", "uint64_t", "unsigned short int", 
+  "unsigned int", "unsigned long int" };
+
+static char *floatOutputTypes[] = {
+  "undef", "undef", "float", "double", "undef", "float", "double" };
+
+
+/* Dynamic memory allocation and freeing */
+
+void * memAlloc(int size);
+char *allocAndCopy(char * str);
+char *appendString(char *s, char *suffix);
+void freeTypes(sequence *t);
+void freeType(type_descriptor * td);
+void freeEvents(sequence *t);
+void freeNamedType(table * t);
+void error_callback(parse_file *in, char *msg);
+
+
+//checksum part
+static const unsigned int crctab32[] =
+{
+#include "crc32.tab"
+};
+
+static inline unsigned long
+partial_crc32_one(unsigned char c, unsigned long crc)
+{
+  return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8);
+}
+
+static inline unsigned long
+partial_crc32(const char *s, unsigned long crc)
+{
+  while (*s)
+    crc = partial_crc32_one(*s++, crc);
+  return crc;
+}
+
+static inline unsigned long
+crc32(const char *s)
+{
+  return partial_crc32(s, 0xffffffff) ^ 0xffffffff;
+}
+
+
+#endif // PARSER_H
diff --git a/ltt/branches/poly/ltt/tracefile.c b/ltt/branches/poly/ltt/tracefile.c
new file mode 100644 (file)
index 0000000..f16124f
--- /dev/null
@@ -0,0 +1,993 @@
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <linux/errno.h>  
+
+#include "LTTTypes.h"  
+#include "parser.h"
+#include <ltt/tracefile.h>
+
+#include "default.h"  //yxx test
+
+/* set the offset of the fields belonging to the event,
+   need the information of the archecture */
+void setFieldsOffset(ltt_tracefile * t, ltt_eventtype *evT, void *evD);
+
+/* get the size of the field type according to the archtecture's
+   size and endian type(info of the archecture) */
+int getFieldtypeSize(ltt_tracefile * t, ltt_eventtype * evT, int offsetRoot,
+                    int offsetParent, ltt_field * fld, void * evD );
+
+/* read a fixed size or a block information from the file (fd) */
+int readFile(int fd, void * buf, size_t size, char * mesg);
+int readBlock(ltt_tracefile * tf, int whichBlock);
+
+/* calculate cycles per nsec for current block */
+void getCyclePerNsec(ltt_tracefile * t);
+
+/* functions to release the memory occupied by the tables of a tracefile */
+void freeKey (gpointer key, gpointer value, gpointer user_data);
+void freeValue (gpointer key, gpointer value, gpointer user_data);
+void freeFacilityNameTable (gpointer key, gpointer value, gpointer user_data);
+
+/* reinitialize the info of the block which is already in the buffer */
+void updateTracefile(ltt_tracefile * tf);
+
+/* go to the next event */
+int skipEvent(ltt_tracefile * t);
+
+/* compare two time (ltt_time), 0:t1=t2, -1:t1<t2, 1:t1>t2 */
+int timecmp(ltt_time * t1, ltt_time * t2);
+
+/* get an integer number */
+int getIntNumber(int size1, void *evD);
+
+
+/* Time operation macros for ltt_time (struct timespec) */
+/*  (T3 = T2 - T1) */
+#define TimeSub(T3, T2, T1) \
+do \
+{\
+  (T3).tv_sec  = (T2).tv_sec  - (T1).tv_sec;  \
+  (T3).tv_nsec = (T2).tv_nsec - (T1).tv_nsec; \
+  if((T3).tv_nsec < 0)\
+    {\
+    (T3).tv_sec--;\
+    (T3).tv_nsec += 1000000000;\
+    }\
+} while(0)
+
+/*  (T3 = T2 + T1) */
+#define TimeAdd(T3, T2, T1) \
+do \
+{\
+  (T3).tv_sec  = (T2).tv_sec  + (T1).tv_sec;  \
+  (T3).tv_nsec = (T2).tv_nsec + (T1).tv_nsec; \
+  if((T3).tv_nsec >= 1000000000)\
+    {\
+    (T3).tv_sec += (T3).tv_nsec / 1000000000;\
+    (T3).tv_nsec = (T3).tv_nsec % 1000000000;\
+    }\
+} while(0)
+
+
+
+/*****************************************************************************
+ *Function name
+ *    ltt_tracefile_open : open a trace file, construct a ltt_tracefile
+ *Input params
+ *    pathname           : path name of the trace file
+ *Return value
+ *    ltt_tracefile *    : the structure represents the opened trace file
+ ****************************************************************************/ 
+
+ltt_tracefile *ltt_tracefile_open(char * fileName)
+{
+  ltt_tracefile * tf;
+  struct stat      lTDFStat;    /* Trace data file status */
+  trace_header_event *trace_header;
+  block_header   a_block_header;
+
+  tf = g_new(ltt_tracefile, 1);
+
+  //open the file
+  tf->fd = open(fileName, O_RDONLY, 0);
+  if(tf->fd < 0){
+    g_error("Unable to open input data file %s\n", fileName);
+  }
+  // Get the file's status 
+  if(fstat(tf->fd, &lTDFStat) < 0){
+    g_error("Unable to get the status of the input data file %s\n", fileName);
+  }
+
+  // Is the file large enough to contain a trace 
+  if(lTDFStat.st_size < sizeof(block_header) + sizeof(trace_header_event)){
+    g_error("The input data file %s does not contain a trace\n", fileName);
+  }
+  
+  //store the size of the file
+  tf->file_size = lTDFStat.st_size;
+
+  //read the first block header
+  if(readFile(tf->fd,(void*)&a_block_header, sizeof(block_header),
+              "Unable to read block header"))
+    exit(1);
+  
+  //read the trace header event
+  trace_header = g_new(trace_header_event, 1);
+  if(readFile(tf->fd,(void*)trace_header, sizeof(trace_header_event),
+              "Unable to read trace header event"))
+    exit(1);
+
+  tf->block_number = tf->file_size / trace_header->buffer_size;
+  tf->trace_header = (trace_header_event *)trace_header;
+
+  //allocate memory to contain the info of a block
+  tf->buffer = (void *) g_new(char, trace_header->buffer_size);
+
+  //read the last block, get the trace end time
+  if(readBlock(tf,tf->block_number)) exit(1);
+  tf->end_time = tf->a_block_footer->time;
+
+  //read the first block, get the trace start time
+  if(tf->block_number != 1)
+    if(readBlock(tf,1)) exit(1);
+  tf->start_time = tf->a_block_header->time;
+
+  //get local machine's data type size and endian type
+  getDataEndianType(&(tf->my_arch_size), &(tf->my_arch_endian));
+
+  //initialize all tables
+  tf->eventtype_number   = 0;
+  tf->facility_number    = 0;
+  tf->index_facility     = g_hash_table_new (g_int_hash, g_int_equal);
+  tf->facility_name      = g_hash_table_new (g_str_hash, g_str_equal);
+  tf->base_id_name       = g_hash_table_new (g_str_hash, g_int_equal);
+  tf->eventtype_event_id = g_ptr_array_new();
+
+  return tf;
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_tracefile_close: close a trace file, release all facilities if their
+ *                         usage count == 0 when close_facilities is true
+ *Input params
+ *    t                  : tracefile which will be closed
+ *    close_facilities   : bool to show if the facilities need to be released
+ *Return value
+ *    int                : ????
+ ****************************************************************************/
+
+int ltt_tracefile_close(ltt_tracefile *t, int close_facilities)
+{
+  //free index_facility table
+  g_hash_table_foreach (t->index_facility, freeKey, NULL);
+  g_hash_table_destroy(t->index_facility);
+
+  //free base_id_facility table
+  g_hash_table_foreach (t->base_id_name, freeValue, NULL);
+  g_hash_table_destroy(t->base_id_name);
+
+  //free eventtype_event_id array
+  g_ptr_array_free (t->eventtype_event_id, TRUE);
+
+  //free facility_name table
+  g_hash_table_foreach (t->facility_name, freeFacilityNameTable,
+                       GINT_TO_POINTER(1));
+  g_hash_table_destroy(t->facility_name);  
+
+  //free tracefile structure
+  g_free(t->trace_header);
+  g_free(t->buffer);
+  g_free(t);
+  return 0;
+}
+
+/*****************************************************************************
+ * functions to release the memory occupied by the tables of a tracefile
+ ****************************************************************************/
+
+void freeKey (gpointer key, gpointer value, gpointer user_data)
+{
+  g_free(key);
+}
+
+void freeValue (gpointer key, gpointer value, gpointer user_data)
+{
+  g_free(value);
+}
+
+void freeFacilityNameTable (gpointer key, gpointer value, gpointer user_data)
+{
+  ltt_facility * fac = (ltt_facility*) value;
+  fac->usage_count--;
+  if(GPOINTER_TO_INT(user_data) != 0)
+    ltt_facility_close(fac);    
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_tracefile_facility_add: increases the facility usage count and also 
+ *                                specifies the base of the numeric range
+ *                                assigned to the event types in the facility 
+ *                                for this tracefile
+ *Input params
+ *    t                  : tracefile that the facility will be added
+ *    f                  : facility that will be attached to the tracefile
+ *    base_id            : the id for the first event of the facility in the 
+ *                         trace file
+ *Return value
+ *    int                : ????
+ ****************************************************************************/
+
+int ltt_tracefile_facility_add(ltt_tracefile *t,ltt_facility *f,int base_id)
+{
+  int * id, *index;
+  int i, j, k;
+  ltt_eventtype * et;
+  gpointer tmpPtr;
+
+  //increase the facility usage count
+  f->usage_count++;
+  t->eventtype_number += f->event_number;
+  t->facility_number++;
+
+  //insert the facility into index_facility table
+  id = g_new(int,1);
+  *id = t->facility_number;
+  g_hash_table_insert(t->index_facility, (gpointer)id,(gpointer)f);  
+
+  //insert facility name into table: base_id_name
+  id = g_new(int,1);
+  *id = base_id;
+  g_hash_table_insert(t->base_id_name, (gpointer)(f->name), (gpointer)id);
+
+  //insert facility name into table: facility_name
+  g_hash_table_insert(t->facility_name, (gpointer)(f->name), (gpointer)f);
+  
+  //insert eventtype into the array: eventtype_event_id
+  j = base_id + f->event_number;
+  k = t->eventtype_event_id->len;
+  if(j > t->eventtype_event_id->len){
+    for(i=0; i < j - k; i++){
+      tmpPtr = (gpointer)g_new(ptr_wrap, 1);
+      g_ptr_array_add(t->eventtype_event_id,tmpPtr);
+    }
+  }
+
+  //initialize the unused elements: NULL
+  if(j-k > f->event_number){
+    for(i=k; i<base_id; i++){
+      tmpPtr = g_ptr_array_index(t->eventtype_event_id, i);
+      ((ptr_wrap*)tmpPtr)->ptr = NULL;
+    }
+  }
+
+  //initialize the elements with the eventtypes belonging to the facility
+  for(i=0; i<f->event_number; i++){
+    tmpPtr = g_ptr_array_index(t->eventtype_event_id, base_id + i);
+    ((ptr_wrap*)tmpPtr)->ptr = (gpointer)(f->events[i]);
+  }
+  
+  //update offset
+  for(i=0; i<f->event_number; i++){
+    et = f->events[i];
+    setFieldsOffset(t, et, NULL);
+  }
+
+
+  return 0;
+}
+
+/*****************************************************************************
+ * The following functions used to query the info of the machine where the 
+ * tracefile was generated.  A tracefile may be queried for its architecture 
+ * type(e.g.,"i386", "powerpc", "powerpcle", "s390", "s390x"), its architecture
+ * variant(e.g., "att" versus "sun" for m68k), its operating system (e.g., 
+ * "linux","bsd"), its generic architecture, and the machine identity (e.g., 
+ * system host name). All character strings belong to the associated tracefile 
+ * and are freed when it is closed
+ ****************************************************************************/
+
+uint32_t ltt_tracefile_arch_type(ltt_tracefile *t)
+{
+  return t->trace_header->arch_type;
+}  
+
+uint32_t ltt_tracefile_arch_variant(ltt_tracefile *t)
+{
+  return t->trace_header->arch_variant;
+}
+
+ltt_arch_size ltt_tracefile_arch_size(ltt_tracefile *t)
+{
+  return t->trace_header->arch_size;
+}
+
+ltt_arch_endian ltt_tracefile_arch_endian(ltt_tracefile *t)
+{
+  return t->trace_header->arch_endian;
+} 
+
+uint32_t ltt_tracefile_system_type(ltt_tracefile *t)
+{
+  return t->trace_header->system_type;
+}
+
+char *ltt_tracefile_system_name(ltt_tracefile *t)
+{
+  return t->trace_header->system_name;
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_tracefile_cpu_number: get the number of the cpu
+ *Input params
+ *    t                       : tracefile
+ *Return value
+ *    unsigned                : the number of cpu the system has
+ ****************************************************************************/
+
+unsigned ltt_tracefile_cpu_number(ltt_tracefile *t)
+{
+  return (unsigned)(t->trace_header->cpu_number);
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_tracefile_cpu_single: does the tracefile contain events only for a 
+ *                              single CPU ?
+ *Input params
+ *    t                       : tracefile
+ *Return value
+ *    int                     : 1 for YES, 0 for NO
+ ****************************************************************************/
+
+int ltt_tracefile_cpu_single(ltt_tracefile *t)
+{
+  if(t->trace_header->cpu_number_used == 1) return 1;
+  else return 0;
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_tracefile_cpu_id: which CPU is contained in the tracefile?
+ *Input params
+ *    t                   : tracefile
+ *Return value
+ *    unsigned            : cpu id
+ ****************************************************************************/
+
+unsigned ltt_tracefile_cpu_id(ltt_tracefile *t)
+{
+  return (unsigned)(t->trace_header->cpu_id);
+}
+
+/*****************************************************************************
+ * The following functions get the times related to the tracefile
+ ****************************************************************************/
+
+ltt_time ltt_tracefile_time_start(ltt_tracefile *t)
+{
+  return t->start_time;
+}
+
+ltt_time ltt_tracefile_time_end(ltt_tracefile *t)
+{
+  return t->end_time;
+}
+
+ltt_time ltt_tracefile_duration(ltt_tracefile *t)
+{
+  ltt_time T;
+  TimeSub(T, t->end_time, t->start_time);
+  return T;
+}
+
+/*****************************************************************************
+ * The following functions discover the facilities added to the tracefile
+ ****************************************************************************/
+
+unsigned ltt_tracefile_facility_number(ltt_tracefile *t)
+{
+  return (unsigned)(t->facility_number);
+}
+
+ltt_facility *ltt_tracefile_facility_get(ltt_tracefile *t, unsigned i)
+{
+  gconstpointer ptr = (gconstpointer)(&i);
+  if(i<=0 || i> t->facility_number)return NULL;
+  return (ltt_facility*)g_hash_table_lookup(t->index_facility,ptr);
+}
+
+ltt_facility *ltt_tracefile_facility_get_by_name(ltt_tracefile *t,char *name)
+{
+  ltt_facility * fac;
+  fac=(ltt_facility*)g_hash_table_lookup(t->facility_name,(gconstpointer)name);
+  return fac;
+}
+
+/*****************************************************************************
+ * The following functions to discover all the event types in the facilities 
+ * added to the tracefile. The event type integer id, unique for the trace, 
+ * is used
+ ****************************************************************************/
+
+unsigned ltt_tracefile_eventtype_number(ltt_tracefile *t)
+{
+  return t->eventtype_number;
+}
+
+ltt_eventtype *ltt_tracefile_eventtype_get(ltt_tracefile *t, unsigned evId)
+{
+  ptr_wrap * ptr;
+  ptr = (ptr_wrap *)g_ptr_array_index(t->eventtype_event_id, (gint)evId);
+  return (ltt_eventtype *)(ptr->ptr);
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_tracefile_eventtype_id
+ *                        : given an event type, find its unique id within 
+ *                          the tracefile
+ *Input params
+ *    t                   : tracefile
+ *    et                  : event type
+ *Return value
+ *    unsigned            : id of the event type in the tracefile
+ ****************************************************************************/
+
+unsigned ltt_tracefile_eventtype_id(ltt_tracefile *t, ltt_eventtype *et)
+{
+  int *id;
+  char *name = et->facility->name;
+  
+  id = (int*)g_hash_table_lookup(t->base_id_name, (gconstpointer)name);
+  if(!id)return 0;
+  return (unsigned)(*id + et->index);
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_tracefile_eventtype_root_field
+ *                        : get the root field associated with an event type
+ *                          for the tracefile
+ *Input params
+ *    t                   : tracefile
+ *    id                  : event id
+ *Return value
+ *    ltt_field *         : root field of the event
+ ****************************************************************************/
+
+ltt_field *ltt_tracefile_eventtype_root_field(ltt_tracefile *t, unsigned id)
+{
+  ltt_eventtype * et;
+  et = ltt_tracefile_eventtype_get(t, id);
+  if(!et) return NULL;
+  return et->root_field;
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_tracefile_seek_time: seek to the first event of the trace with time 
+ *                             larger or equal to time
+ *Input params
+ *    t                      : tracefile
+ *    time                   : criteria of the time
+ *Return value
+ *    int                    : error code
+ *                             ENOENT, end of the file
+ *                             EINVAL, lseek fail
+ *                             EIO, can not read from the file
+ ****************************************************************************/
+
+int ltt_tracefile_seek_time(ltt_tracefile *t, ltt_time time)
+{
+  int err;
+  ltt_time lttTime;
+  int headTime = timecmp(&(t->a_block_header->time), &time);
+  int tailTime = timecmp(&(t->a_block_footer->time), &time);
+  
+  if(headTime < 0 && tailTime > 0){
+    lttTime = getEventTime(t);
+    err = timecmp(&lttTime, &time);
+    if(err >= 0){
+      if( ( (t->which_block != 1 && t->which_event != 0) ||
+            (t->which_block == 1 && t->which_event != 1)   ) &&
+          ((t->prev_event_time.tv_sec==0 && t->prev_event_time.tv_nsec==0) ||
+          timecmp(&t->prev_event_time, &time) >= 0 )  ){
+       updateTracefile(t);
+       return ltt_tracefile_seek_time(t, time);
+      }
+    }else if(err < 0){
+      err = t->which_block;
+      if(ltt_tracefile_read(t) == NULL) return ENOENT;      
+      if(t->which_block == err)
+       return ltt_tracefile_seek_time(t,time);
+    }    
+  }else if(headTime > 0){
+    if(t->which_block == 1){
+      updateTracefile(t);      
+    }else{
+      if( (t->prev_block_end_time.tv_sec == 0 && 
+          t->prev_block_end_time.tv_nsec == 0  ) ||
+          timecmp(&(t->prev_block_end_time),&time) > 0 ){
+       err=readBlock(t,t->which_block-1);
+       if(err) return err; 
+       return ltt_tracefile_seek_time(t, time) ;
+      }else{
+       updateTracefile(t);
+      }
+    }
+  }else if(tailTime <= 0){
+    if(t->which_block != t->block_number){
+      err=readBlock(t,t->which_block+1);
+      if(err) return err; 
+    }else return ENOENT;    
+    if(tailTime < 0) return ltt_tracefile_seek_time(t, time);
+  }else if(headTime == 0){
+    updateTracefile(t);
+  }
+  return 0;
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_tracefile_read : read the next event 
+ *Input params
+ *    t                  : tracefile
+ *Return value
+ *    ltt_event *        : an event to be processed
+ ****************************************************************************/
+
+ltt_event *ltt_tracefile_read(ltt_tracefile *t)
+{
+  ltt_event * lttEvent = (ltt_event *)g_new(ltt_event, 1);
+  ltt_eventtype * evT;
+  ltt_facility * fac;
+
+  //update the fields of the current event and go to the next event
+  if(skipEvent(t)) return NULL;
+
+  t->current_event_time = getEventTime(t);
+
+  lttEvent->event_id = (int)(*(uint8_t *)(t->cur_event_pos));
+  evT = ltt_tracefile_eventtype_get(t, (unsigned)lttEvent->event_id);
+  fac = evT->facility;
+  if(evT->index == TRACE_EV_HEARTBEAT && strcmp(fac->name, "default")==0)
+    t->cur_heart_beat_number++;
+  lttEvent->cycle_count=*(uint32_t*)(t->cur_event_pos + EVENT_ID_SIZE);
+  lttEvent->tracefile = t;
+  lttEvent->data = t->cur_event_pos + EVENT_HEADER_SIZE;  
+
+  return lttEvent;
+}
+
+/****************************************************************************
+ *Function name
+ *    readFile    : wrap function to read from a file
+ *Input Params
+ *    fd          : file descriptor
+ *    buf         : buf to contain the content
+ *    size        : number of bytes to be read
+ *    mesg        : message to be printed if some thing goes wrong
+ *return value 
+ *    0           : success
+ *    EIO         : can not read from the file
+ ****************************************************************************/
+
+int readFile(int fd, void * buf, size_t size, char * mesg)
+{
+   ssize_t nbBytes;
+   nbBytes = read(fd, buf, size);
+   if(nbBytes != size){
+     printf("%s\n",mesg);
+     return EIO;
+   }
+   return 0;
+}
+
+/****************************************************************************
+ *Function name
+ *    readBlock       : read a block from the file
+ *Input Params
+ *    lttdes          : ltt trace file 
+ *    whichBlock      : the block which will be read
+ *return value 
+ *    0               : success
+ *    EINVAL          : lseek fail
+ *    EIO             : can not read from the file
+ ****************************************************************************/
+
+int readBlock(ltt_tracefile * tf, int whichBlock)
+{
+  off_t nbBytes;
+  uint32_t lostSize;
+
+  if(whichBlock - tf->which_block == 1 && tf->which_block != 0){
+    tf->prev_block_end_time = tf->a_block_footer->time;
+  }else{
+    tf->prev_block_end_time.tv_sec = 0;
+    tf->prev_block_end_time.tv_nsec = 0;
+  }
+  tf->prev_event_time.tv_sec = 0;
+  tf->prev_event_time.tv_nsec = 0;
+
+  nbBytes=lseek(tf->fd,(off_t)((whichBlock-1)*tf->trace_header->buffer_size),
+                  SEEK_SET);
+  if(nbBytes == -1) return EINVAL;
+  
+  if(readFile(tf->fd,tf->buffer,tf->trace_header->buffer_size,
+              "Unable to read a block")) return EIO;
+
+
+  tf->a_block_header=(block_header *) tf->buffer;
+  lostSize = *(uint32_t*)(tf->buffer + tf->trace_header->buffer_size 
+                         - sizeof(uint32_t));
+  /* skip event ID and time delta to get the address of the block foot */
+  tf->a_block_footer=(block_footer *)(tf->buffer+tf->trace_header->buffer_size
+                                   -lostSize+sizeof(uint8_t)+sizeof(uint32_t)); 
+  tf->which_block = whichBlock;
+  tf->which_event = 0;
+  tf->first_event_pos = tf->buffer + sizeof(block_header);
+  if(tf->which_block == 1){
+    tf->which_event++;
+    tf->first_event_pos += sizeof(trace_header_event);
+  }
+  tf->cur_event_pos = tf->first_event_pos;
+  tf->current_event_time = tf->a_block_header->time;
+  tf->cur_heart_beat_number = 0;
+  
+  getCyclePerNsec(tf);
+
+  return 0;  
+}
+
+/*****************************************************************************
+ *Function name
+ *    updateTracefile : reinitialize the info of the block which is already 
+ *                      in the buffer
+ *Input params 
+ *    tf              : tracefile
+ ****************************************************************************/
+
+void updateTracefile(ltt_tracefile * tf)
+{
+  if(tf->which_block == 1)tf->which_event = 1;
+  else tf->which_event = 0;
+  tf->cur_event_pos = tf->first_event_pos;
+  tf->current_event_time = tf->a_block_header->time;  
+  tf->cur_heart_beat_number = 0;
+
+  tf->prev_event_time.tv_sec = 0;
+  tf->prev_event_time.tv_nsec = 0;
+}
+
+/*****************************************************************************
+ *Function name
+ *    skipEvent : go to the next event, update the fields of the current event
+ *Input params 
+ *    t         : tracefile
+ *return value 
+ *    0               : success
+ *    EINVAL          : lseek fail
+ *    EIO             : can not read from the file
+ *    ENOENT          : end of file
+ *    ERANGE          : event id is out of range
+ ****************************************************************************/
+
+int skipEvent(ltt_tracefile * t)
+{
+  int evId, err;
+  void * evData;
+  ltt_eventtype * evT;
+  ltt_field * rootFld;
+
+  evId   = (int)(*(uint8_t *)(t->cur_event_pos));
+  evData = t->cur_event_pos + EVENT_HEADER_SIZE;
+  evT    = ltt_tracefile_eventtype_get(t,(unsigned)evId);
+
+  if(evT) rootFld = evT->root_field;
+  else return ERANGE;
+
+  t->prev_event_time = getEventTime(t);
+  
+  //event has string/sequence or the last event is not the same event
+  if((evT->latest_block!=t->which_block || evT->latest_event!=t->which_event) 
+     && rootFld->field_fixed == 0){
+    setFieldsOffset(t, evT, evData);
+  }
+  t->cur_event_pos += EVENT_HEADER_SIZE + rootFld->field_size;
+
+  evT->latest_block = t->which_block;
+  evT->latest_event = t->which_event;
+  
+  //the next event is in the next block
+  if(t->which_event == t->a_block_header->event_count - 1){
+    if(t->which_block == t->block_number) return ENOENT;
+    err = readBlock(t, t->which_block + 1);
+    if(err) return err;
+  }else{
+    t->which_event++;
+  }
+
+  return 0;
+}
+
+/*****************************************************************************
+ *Function name
+ *    getCyclePerNsec : calculate cycles per nsec for current block
+ *Input Params
+ *    t               : tracefile
+ ****************************************************************************/
+
+void getCyclePerNsec(ltt_tracefile * t)
+{
+  ltt_time            lBufTotalTime; /* Total time for this buffer */
+  ltt_cycle_count     lBufTotalNSec; /* Total time for this buffer in nsecs */
+  ltt_cycle_count     lBufTotalCycle;/* Total cycles for this buffer */
+
+  /* Calculate the total time for this buffer */
+  TimeSub(lBufTotalTime,t->a_block_footer->time, t->a_block_header->time);
+
+  /* Calculate the total cycles for this bufffer */
+  lBufTotalCycle = t->a_block_footer->cycle_count 
+                   - t->a_block_header->cycle_count;
+
+  /* Convert the total time to nsecs */
+  lBufTotalNSec = lBufTotalTime.tv_sec * 1000000000 + lBufTotalTime.tv_nsec;
+  
+  t->cycle_per_nsec = (double)lBufTotalCycle / (double)lBufTotalNSec;
+}
+
+/****************************************************************************
+ *Function name
+ *    getEventTime    : obtain the time of an event 
+ *Input params 
+ *    tf              : tracefile
+ *Return value
+ *    ltt_time        : the time of the event
+ ****************************************************************************/
+
+ltt_time getEventTime(ltt_tracefile * tf)
+{
+  ltt_time        time;
+  ltt_cycle_count cycle_count;      /* cycle count for the current event */
+  ltt_cycle_count lEventTotalCycle; /* Total cycles from start for event */
+  double          lEventNSec;       /* Total usecs from start for event */
+  ltt_time        lTimeOffset;      /* Time offset in struct ltt_time */
+  
+  /* Calculate total time in cycles from start of buffer for this event */
+  cycle_count = *(uint32_t*)(tf->cur_event_pos + EVENT_ID_SIZE);
+  if(tf->cur_heart_beat_number)
+    cycle_count += ((uint64_t)1)<<32  * tf->cur_heart_beat_number;
+  lEventTotalCycle=cycle_count-(tf->a_block_header->cycle_count & 0xFFFFFFFF);
+
+  /* Convert it to nsecs */
+  lEventNSec = lEventTotalCycle / tf->cycle_per_nsec;
+  
+  /* Determine offset in struct ltt_time */
+  lTimeOffset.tv_nsec = (long)lEventNSec % 1000000000;
+  lTimeOffset.tv_sec  = (long)lEventNSec / 1000000000;
+
+  TimeAdd(time, tf->a_block_header->time, lTimeOffset);  
+
+  return time;
+}
+
+/*****************************************************************************
+ *Function name
+ *    setFieldsOffset : set offset of the fields
+ *Input params 
+ *    tracefile       : opened trace file  
+ *    evT             : the event type
+ *    evD             : event data, it may be NULL
+ ****************************************************************************/
+
+void setFieldsOffset(ltt_tracefile * t, ltt_eventtype * evT, void * evD)
+{
+  ltt_field * rootFld = evT->root_field;
+  //  rootFld->base_address = evD;
+
+  rootFld->field_size = getFieldtypeSize(t, evT, 0,0,rootFld, evD);  
+}
+
+/*****************************************************************************
+ *Function name
+ *    getFieldtypeSize: get the size of the field type (primitive type)
+ *Input params 
+ *    tracefile       : opened trace file 
+ *    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
+ ****************************************************************************/
+
+int getFieldtypeSize(ltt_tracefile * t, ltt_eventtype * evT, int offsetRoot,
+                    int offsetParent, ltt_field * fld, void * evD)
+{
+  int size, size1, element_number, i, offset1, offset2;
+  ltt_type * type = fld->field_type;
+
+  if(evT->latest_block==t->which_block && evT->latest_event==t->which_event){
+    return fld->field_size;
+  } 
+
+  if(fld->field_fixed == 1){
+    if(fld == evT->root_field) return fld->field_size;
+  }     
+
+  if(type->type_class != LTT_STRUCT && type->type_class != LTT_ARRAY &&
+     type->type_class != LTT_SEQUENCE && type->type_class != LTT_STRING){
+    if(fld->field_fixed == -1){
+      size = (int) ltt_type_size(t, type);
+      fld->field_fixed = 1;
+    }else size = fld->field_size;
+
+  }else if(type->type_class == LTT_ARRAY){
+    element_number = (int) type->element_number;
+    if(fld->field_fixed == -1){
+      size = getFieldtypeSize(t, 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(t, evT, offsetRoot+size,size, 
+                               fld->child[0], evD+size);
+      }      
+    }else size = fld->field_size;
+
+  }else if(type->type_class == LTT_SEQUENCE){
+    size1 = (int) ltt_type_size(t, type);
+    if(fld->field_fixed == -1){
+      fld->field_fixed = 0;
+      size = getFieldtypeSize(t, evT, offsetRoot,0,fld->child[0], NULL);      
+      fld->element_size = size;
+    }else{//0: sequence
+      element_number = getIntNumber(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(t, evT, offsetRoot+size+size1,size+size1, 
+                                  fld->child[0], evD+size+size1);
+       }       
+      }
+      size += size1;
+    }
+
+  }else if(type->type_class == LTT_STRING){
+    size = 0;
+    if(fld->field_fixed == -1){
+      fld->field_fixed = 0;
+    }else{//0: string
+      size = sizeof((char*)evD) + 1; //include end : '\0'
+    }
+
+  }else if(type->type_class == LTT_STRUCT){
+    element_number = (int) type->element_number;
+    size = 0;
+    if(fld->field_fixed == -1){      
+      offset1 = offsetRoot;
+      offset2 = 0;
+      for(i=0;i<element_number;i++){
+       size1=getFieldtypeSize(t, evT,offset1,offset2, fld->child[i], NULL);
+       if(size1 > 0 && size >= 0){
+         size += size1;
+         if(offset1 >= 0) offset1 += size1;
+         offset2 += size1;
+       }else{
+         size = -1;
+         offset1 = -1;
+         offset2 = -1;
+       }
+      }
+      if(size == -1){
+       fld->field_fixed = 0;
+       size = 0;
+      }else fld->field_fixed = 1;
+    }else if(fld->field_fixed == 0){
+      offset1 = offsetRoot;
+      offset2 = 0;
+      for(i=0;i<element_number;i++){
+       size=getFieldtypeSize(t,evT,offset1,offset2,fld->child[i],evD+offset2);
+       offset1 += size;
+       offset2 += size;
+      }      
+      size = offset2;
+    }else size = fld->field_size;
+  }
+
+  fld->offset_root     = offsetRoot;
+  fld->offset_parent   = offsetParent;
+  if(!evD){
+    fld->fixed_root    = (offsetRoot==-1)   ? 0 : 1;
+    fld->fixed_parent  = (offsetParent==-1) ? 0 : 1;
+  }
+  fld->field_size      = size;
+
+  return size;
+}
+
+/*****************************************************************************
+ *Function name
+ *    timecmp   : compare two time
+ *Input params 
+ *    t1        : first time
+ *    t2        : second time
+ *Return value
+ *    int       : 0: t1 == t2; -1: t1 < t2; 1: t1 > t2
+ ****************************************************************************/
+
+int timecmp(ltt_time * t1, ltt_time * t2)
+{
+  ltt_time T;
+  TimeSub(T, *t1, *t2);
+  if(T.tv_sec == 0 && T.tv_nsec == 0) return 0;
+  else if(T.tv_sec > 0 || (T.tv_sec==0 && T.tv_nsec > 0)) return 1;
+  else return -1;
+}
+
+/*****************************************************************************
+ *Function name
+ *    getIntNumber    : get an integer number
+ *Input params 
+ *    size            : the size of the integer
+ *    evD             : the event data
+ *Return value
+ *    int             : an integer
+ ****************************************************************************/
+
+int getIntNumber(int size, void *evD)
+{
+  int64_t i;
+  if(size == 1)      i = *(int8_t *)evD;
+  else if(size == 2) i = *(int16_t *)evD;
+  else if(size == 4) i = *(int32_t *)evD;
+  else if(size == 8) i = *(int64_t *)evD;
+  return (int) i;
+}
+
+/*****************************************************************************
+ *Function name
+ *    getDataEndianType : get the data type size and endian type of the local
+ *                        machine
+ *Input params 
+ *    size              : size of data type
+ *    endian            : endian type, little or big
+ ****************************************************************************/
+
+void getDataEndianType(ltt_arch_size * size, ltt_arch_endian * endian)
+{
+  int i = 1;
+  char c = (char) i;
+  int sizeInt=sizeof(int), sizeLong=sizeof(long), sizePointer=sizeof(void *);
+
+  if(c == 1) *endian = LTT_LITTLE_ENDIAN;
+  else *endian = LTT_BIG_ENDIAN;
+
+  if(sizeInt == 2 && sizeLong == 4 && sizePointer == 4) 
+    *size = LTT_LP32;
+  else if(sizeInt == 4 && sizeLong == 4 && sizePointer == 4) 
+    *size = LTT_ILP32;
+  else if(sizeInt == 4 && sizeLong == 8 && sizePointer == 8) 
+    *size = LTT_LP64;
+  else if(sizeInt == 8 && sizeLong == 8 && sizePointer == 8) 
+    *size = LTT_ILP64;
+  else *size = LTT_UNKNOWN;
+}
+
diff --git a/ltt/branches/poly/ltt/type.c b/ltt/branches/poly/ltt/type.c
new file mode 100644 (file)
index 0000000..9815077
--- /dev/null
@@ -0,0 +1,253 @@
+#include <stdio.h>
+
+#include "LTTTypes.h"  
+#include "parser.h"
+#include <ltt/type.h>
+
+static unsigned intSizes[] = {
+  sizeof(int8_t), sizeof(int16_t), sizeof(int32_t), sizeof(int64_t), 
+  sizeof(short) };
+
+static unsigned floatSizes[] = {
+  0, 0, sizeof(float), sizeof(double), 0, sizeof(float), sizeof(double) };
+
+
+/*****************************************************************************
+ *Function name
+ *    ltt_eventtype_name : get the name of the event type
+ *Input params
+ *    et                 : an  event type   
+ *Return value
+ *    char *             : the name of the event type
+ ****************************************************************************/
+
+char *ltt_eventtype_name(ltt_eventtype *et)
+{
+  return et->name;
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_eventtype_description : get the description of the event type
+ *Input params
+ *    et                 : an  event type   
+ *Return value
+ *    char *             : the description of the event type
+ ****************************************************************************/
+
+char *ltt_eventtype_description(ltt_eventtype *et)
+{
+  return et->description;
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_eventtype_type : get the type of the event type
+ *Input params
+ *    et                 : an  event type   
+ *Return value
+ *    ltt_type *         : the type of the event type
+ ****************************************************************************/
+
+ltt_type *ltt_eventtype_type(ltt_eventtype *et)
+{
+  return et->root_field->field_type;
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_type_name  : get the name of the type
+ *Input params
+ *    t              : a type   
+ *Return value
+ *    char *         : the name of the type
+ ****************************************************************************/
+
+char *ltt_type_name(ltt_type *t)
+{
+  return t->element_name;
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_type_class : get the type class of the type
+ *Input params
+ *    t              : a type   
+ *Return value
+ *    ltt_type_enum  : the type class of the type
+ ****************************************************************************/
+
+ltt_type_enum ltt_type_class(ltt_type *t)
+{
+  return t->type_class;
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_type_size : obtain the type size. The size is the number of bytes 
+ *                    for primitive types (INT, UINT, FLOAT, ENUM), or the 
+ *                    size for the unsigned integer length count for sequences
+ *Input params
+ *    tf            : trace file
+ *    t             : a type   
+ *Return value
+ *    unsigned      : the type size
+ ****************************************************************************/
+
+unsigned ltt_type_size(ltt_tracefile * tf, ltt_type *t)
+{
+  if(t->type_class==LTT_STRUCT || t->type_class==LTT_ARRAY || 
+     t->type_class==LTT_STRING) return 0;
+
+  if(t->type_class == LTT_FLOAT){
+    return floatSizes[t->size];
+  }else{
+    if(t->size < sizeof(intSizes)/sizeof(unsigned))
+      return intSizes[t->size];
+    else{
+      ltt_arch_size size = tf->trace_header->arch_size;
+      if(size == LTT_LP32)
+       return sizeof(int16_t);
+      else if(size == LTT_ILP32 || size == LTT_LP64)
+       return sizeof(int32_t);
+      else if(size == LTT_ILP64)
+       return sizeof(int64_t); 
+    }
+  }
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_type_element_type : obtain the type of nested elements for arrays 
+ *                            and sequences 
+ *Input params
+ *    t                     : a type   
+ *Return value
+ *    ltt_type              : the type of nested element of array or sequence
+ ****************************************************************************/
+
+ltt_type *ltt_type_element_type(ltt_type *t)
+{
+  if(t->type_class != LTT_ARRAY || t->type_class != LTT_SEQUENCE)
+    return NULL;
+  return t->element_type[0];
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_type_element_number : obtain the number of elements for arrays 
+ *Input params
+ *    t                       : a type   
+ *Return value
+ *    unsigned                : the number of elements for arrays
+ ****************************************************************************/
+
+unsigned ltt_type_element_number(ltt_type *t)
+{
+  if(t->type_class != LTT_ARRAY)
+    return 0;
+  return t->element_number;
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_type_member_number : obtain the number of data members for structure 
+ *Input params
+ *    t                      : a type   
+ *Return value
+ *    unsigned               : the number of members for structure
+ ****************************************************************************/
+
+unsigned ltt_type_member_number(ltt_type *t)
+{
+  if(t->type_class != LTT_STRUCT)
+    return 0;
+  return t->element_number;  
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_type_member_type : obtain the type of a data members in a structure 
+ *Input params
+ *    t                    : a type   
+ *    i                    : index of the member
+ *Return value
+ *    ltt_type *           : the type of structure member
+ ****************************************************************************/
+
+ltt_type *ltt_type_member_type(ltt_type *t, unsigned i)
+{
+  if(t->type_class != LTT_STRUCT) return NULL;
+  if(i > t->element_number || i == 0 ) return NULL;
+  return t->element_type[i-1];
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_enum_string_get : for enumerations, obtain the symbolic string 
+ *                          associated with a value (0 to n - 1 for an 
+ *                          enumeration of n elements) 
+ *Input params
+ *    t                   : a type   
+ *    i                   : index of the member
+ *Return value
+ *    char *              : symbolic string associated with a value
+ ****************************************************************************/
+
+char *ltt_enum_string_get(ltt_type *t, unsigned i)
+{  
+  if(t->type_class != LTT_ENUM) return NULL;
+  if(i > t->element_number || i == 0 ) return NULL;
+  return t->enum_strings[i-1];
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_field_element : obtain the field of nested elements for arrays and
+ *                        sequence 
+ *Input params
+ *    f                 : a field   
+ *Return value
+ *    ltt_field *       : the field of the nested element
+ ****************************************************************************/
+
+ltt_field *ltt_field_element(ltt_field *f)
+{
+  if(f->field_type->type_class != LTT_ARRAY ||
+     f->field_type->type_class != LTT_SEQUENCE)
+    return NULL;
+
+  return f->child[0];
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_field_member  : obtain the filed of data members for structure
+ *Input params
+ *    f                 : a field   
+ *    i                 : index of member field
+ *Return value
+ *    ltt_field *       : the field of the nested element
+ ****************************************************************************/
+
+ltt_field *ltt_field_member(ltt_field *f, unsigned i)
+{
+  if(f->field_type->type_class != LTT_STRUCT) return NULL;
+  if(i==0 || i>f->field_type->element_number) return NULL;
+  return f->child[i-1];
+}
+
+/*****************************************************************************
+ *Function name
+ *    ltt_field_type  : obtain the type of the field 
+ *Input params
+ *    f               : a field   
+ *Return value
+ *    ltt_tyoe *      : the type of field
+ ****************************************************************************/
+
+ltt_type *ltt_field_type(ltt_field *f)
+{
+  return f->field_type;
+}
+
This page took 0.05411 seconds and 4 git commands to generate.