--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+ 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
--- /dev/null
+#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));
+}
--- /dev/null
+#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;
+}
+
--- /dev/null
+/*
+
+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;
+}
+
+
--- /dev/null
+#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
--- /dev/null
+#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(<tTime, &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;
+}
+
--- /dev/null
+#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;
+}
+