From: yangxx Date: Fri, 30 May 2003 19:17:22 +0000 (+0000) Subject: first version of reading api source files X-Git-Tag: v0.12.20~3429 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=6cd62ccfe338056a2a7571addbb63e0e16354e86;p=lttv.git first version of reading api source files git-svn-id: http://ltt.polymtl.ca/svn@60 04897980-b3bd-0310-b5e0-8ef037075253 --- diff --git a/ltt/branches/poly/ltt/LTTTypes.h b/ltt/branches/poly/ltt/LTTTypes.h new file mode 100644 index 00000000..2c054a1c --- /dev/null +++ b/ltt/branches/poly/ltt/LTTTypes.h @@ -0,0 +1,142 @@ +/* + * LTTTypes.h + * + * Copyright (C) 2000 Karim Yaghmour (karym@opersys.com). + * + * This is distributed under GPL. + * + * Header for LTT-secific types. + * + * History : + * K.Y. 07/09/2001, Added David Schleef's architecture independent ltt_set_bit/ltt_clear_bit/ltt_test_bit + * JAL, 05/01/2001, Modified PPC bit manipulation functions for x86 compatibility. + * (andy_lowe@mvista.com) + * K.Y., 31/05/2000, Initial typing. + */ + +#ifndef __TRACE_TOOLKIT_TYPES_HEADER__ +#define __TRACE_TOOLKIT_TYPES_HEADER__ + +#include +#include + +#if defined(sun) + +typedef unsigned char u_int8_t; +typedef unsigned short u_int16_t; +typedef unsigned int u_int32_t; +#ifdef _LP64 +typedef unsigned long u_int64_t; +#else /* _ILP32 */ +#if __STDC__ - 0 == 0 && !defined(_NO_LONGLONG) +typedef unsigned long long u_int64_t; +#endif /* __STDC__ - 0 == 0 && !defined(_NO_LONGLONG) */ +#endif /* _LP64 */ + +#endif /* defined(sun) */ + +extern __inline__ int ltt_set_bit(int nr, void * addr) +{ + unsigned char *p = addr; + unsigned char mask = 1 << (nr&7); + unsigned char old; + + p += nr>>3; + old = *p; + *p |= mask; + + return ((old & mask) != 0); +} + +extern __inline__ int ltt_clear_bit(int nr, void * addr) +{ + unsigned char *p = addr; + unsigned char mask = 1 << (nr&7); + unsigned char old; + + p += nr>>3; + old = *p; + *p &= ~mask; + + return ((old & mask) != 0); +} + +extern __inline__ int ltt_test_bit(int nr,void *addr) +{ + unsigned char *p = addr; + unsigned char mask = 1 << (nr&7); + + p += nr>>3; + + return ((*p & mask) != 0); +} + +/* Big-endian/little-endian conversion macros for cross-development. */ +#if TARGET_NATIVE +/* For native development, these conversion macros aren't needed. */ +#define BREV16(x) (x) +#define BREV32(x) (x) +#define BREV64(x) (x) +#define RFT8(db,x) (x) +#define RFT16(db,x) (x) +#define RFT32(db,x) (x) +#define RFT64(db,x) (x) + +/* Non-native development */ +#else + /* BREV16: byte-reverse a 16-bit integer */ +#define BREV16(x) ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8)) + /* BREV32: byte-reverse a 32-bit integer */ +#define BREV32(x) ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \ + | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + /* BREV64: byte-reverse a 64-bit integer */ +#define BREV64(x) ((((x) & 0xff00000000000000) >> 56) \ + | (((x) & 0x00ff000000000000) >> 40) \ + | (((x) & 0x0000ff0000000000) >> 24) \ + | (((x) & 0x000000ff00000000) >> 8) \ + | (((x) & 0x00000000ff000000) << 8) \ + | (((x) & 0x0000000000ff0000) << 24) \ + | (((x) & 0x000000000000ff00) << 40) \ + | (((x) & 0x00000000000000ff) << 56)) + /* RFTn: Read From Trace + * Conditionally byte-reverse an 8-, 16-, 32-, or 64-bit integer + * based on the value of the ByteRev member of the trace database + * structure pointer passed as the first argument.. + */ +#define RFT8(db,x) (x) +#define RFT16(db,x) ((db)->ByteRev ? BREV16(x) : (x)) +#define RFT32(db,x) ((db)->ByteRev ? BREV32(x) : (x)) +#define RFT64(db,x) ((db)->ByteRev ? BREV64(x) : (x)) +#endif /* TRACE_TARGET_NATIVE */ + +#if !defined(sun) +/* Some type corrections, just in case */ +#ifndef uint8_t +#define uint8_t u_int8_t +#endif +#ifndef uint16_t +#define uint16_t u_int16_t +#endif +#ifndef uint32_t +#define uint32_t u_int32_t +#endif +#ifndef uint64_t +#define uint64_t u_int64_t +#endif +#endif /* !defined(sun) */ + +/* Structure packing */ +#if LTT_UNPACKED_STRUCTS +#define LTT_PACKED_STRUCT +#else +#define LTT_PACKED_STRUCT __attribute__ ((packed)) +#endif /* UNPACKED_STRUCTS */ + +/* Trace mask */ +typedef uint64_t trace_event_mask; + +/* Boolean stuff */ +#define TRUE 1 +#define FALSE 0 + +#endif /* __TRACE_TOOLKIT_TYPES_HEADER__ */ diff --git a/ltt/branches/poly/ltt/crc32.tab b/ltt/branches/poly/ltt/crc32.tab new file mode 100644 index 00000000..d0174ad6 --- /dev/null +++ b/ltt/branches/poly/ltt/crc32.tab @@ -0,0 +1,52 @@ + 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, + 0x706af48fU, 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U, + 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, + 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, + 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U, 0x136c9856U, + 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U, + 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, + 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, + 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, + 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U, 0x26d930acU, 0x51de003aU, + 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, + 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, + 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U, + 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, + 0x9fbfe4a5U, 0xe8b8d433U, 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, + 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U, + 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU, + 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U, + 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, + 0xfbd44c65U, 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, + 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU, + 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U, + 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU, 0xbe0b1010U, + 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU, + 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, + 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U, + 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U, + 0x73dc1683U, 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U, + 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U, 0xf00f9344U, + 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU, + 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, + 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U, + 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, + 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU, 0xd80d2bdaU, 0xaf0a1b4cU, + 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU, + 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U, + 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU, + 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, + 0x2cd99e8bU, 0x5bdeae1dU, 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, + 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U, + 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU, + 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U, + 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, + 0x18b74777U, 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, + 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U, 0xa00ae278U, + 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U, + 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U, + 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U, + 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, + 0xcdd70693U, 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U, + 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, + 0x2d02ef8dU diff --git a/ltt/branches/poly/ltt/event.c b/ltt/branches/poly/ltt/event.c new file mode 100644 index 00000000..20d71d91 --- /dev/null +++ b/ltt/branches/poly/ltt/event.c @@ -0,0 +1,350 @@ +#include +#include +#include + +#include "LTTTypes.h" +#include "parser.h" +#include + +/***************************************************************************** + *Function name + * ltt_facility_eventtype_id: get event type id + * (base id + position of the event) + *Input params + * e : an instance of an event type + *Return value + * unsigned : event type id + ****************************************************************************/ + +unsigned ltt_event_eventtype_id(ltt_event *e) +{ + return (unsigned) e->event_id; +} + +/***************************************************************************** + *Function name + * ltt_event_facility : get the facility of the event + *Input params + * e : an instance of an event type + *Return value + * ltt_facility * : the facility of the event + ****************************************************************************/ + +ltt_facility *ltt_event_facility(ltt_event *e) +{ + ltt_eventtype * evT; + ptr_wrap * ptr; + ptr = (ptr_wrap*)g_ptr_array_index(e->tracefile->eventtype_event_id, + (gint)(e->event_id)); + evT = (ltt_eventtype*)(ptr->ptr); + + if(!evT) return NULL; + return evT->facility; +} + +/***************************************************************************** + *Function name + * ltt_event_eventtype : get the event type of the event + *Input params + * e : an instance of an event type + *Return value + * ltt_eventtype * : the event type of the event + ****************************************************************************/ + +ltt_eventtype *ltt_event_eventtype(ltt_event *e) +{ + ptr_wrap * ptr; + ptr = (ptr_wrap*)g_ptr_array_index(e->tracefile->eventtype_event_id, + (gint)(e->event_id)); + return (ltt_eventtype*)(ptr->ptr); +} + +/***************************************************************************** + *Function name + * ltt_event_time : get the time of the event + *Input params + * e : an instance of an event type + *Return value + * ltt_time : the time of the event + ****************************************************************************/ + +ltt_time ltt_event_time(ltt_event *e) +{ + return getEventTime(e->tracefile); +} + +/***************************************************************************** + *Function name + * ltt_event_time : get the cycle count of the event + *Input params + * e : an instance of an event type + *Return value + * ltt_time : the cycle count of the event + ****************************************************************************/ + +ltt_cycle_count ltt_event_cycle_count(ltt_event *e) +{ + return e->cycle_count; +} + +/***************************************************************************** + *Function name + * ltt_event_cpu_i: get the cpu id where the event happens + *Input params + * e : an instance of an event type + *Return value + * unsigned : the cpu id + ****************************************************************************/ + +unsigned ltt_event_cpu_id(ltt_event *e) +{ + return e->tracefile->trace_header->cpu_id; +} + +/***************************************************************************** + *Function name + * ltt_event_cpu_i: get the name of the system where the event happens + *Input params + * e : an instance of an event type + *Return value + * char * : the name of the system + ****************************************************************************/ + +char *ltt_event_system_name(ltt_event *e) +{ + return e->tracefile->trace_header->system_name; +} + +/***************************************************************************** + *Function name + * ltt_event_data : get the raw data for the event + *Input params + * e : an instance of an event type + *Return value + * void * : pointer to the raw data for the event + ****************************************************************************/ + +void *ltt_event_data(ltt_event *e) +{ + return e->data; +} + +/***************************************************************************** + *Function name + * ltt_event_field_element_number + * : The number of elements in a sequence field is specific + * to each event. This function returns the number of + * elements for an array or sequence field in an event. + *Input params + * e : an instance of an event type ???? + * f : a field of the instance + *Return value + * unsigned : the number of elements for an array/sequence field + ****************************************************************************/ + +unsigned ltt_event_field_element_number(ltt_event *e, ltt_field *f) +{ + if(f->field_type->type_class != LTT_ARRAY && + f->field_type->type_class != LTT_SEQUENCE) + return 0; + + return f->field_type->element_number; +} + +/***************************************************************************** + *Function name + * ltt_event_field_element_select + * : Set the currently selected element for a sequence or + * array field + *Input params + * e : an instance of an event type ???? + * f : a field of the instance + * i : the ith element + *Return value + * int : ???? error number + ****************************************************************************/ + +int ltt_event_field_element_select(ltt_event *e, ltt_field *f, unsigned i) +{ + if(f->field_type->type_class != LTT_ARRAY && + f->field_type->type_class != LTT_SEQUENCE) + return -1; //????? + + if(f->field_type->element_number < i || i == 0) return -1; //???? + + f->current_element = i - 1; + return 0; +} + +/***************************************************************************** + * These functions extract data from an event after architecture specific + * conversions + ****************************************************************************/ + +unsigned ltt_event_get_unsigned(ltt_event *e, ltt_field *f) +{ + ltt_arch_size rSize = e->tracefile->trace_header->arch_size; + int revFlag = e->tracefile->my_arch_endian == + e->tracefile->trace_header->arch_endian ? 0:1; + ltt_type_enum t = f->field_type->type_class; + + if(t != LTT_UINT || t != LTT_ENUM) + g_error("The type of the field is not unsigned int\n"); + + if(rSize == LTT_LP32){ + if(f->field_size != 2) + g_error("The type of the field is not unsigned int: uint16_t\n"); + else{ + uint16_t x = *(uint16_t *)(e->data + f->offset_root); + return (unsigned) (revFlag ? BREV16(x) : x); + } + }else if(rSize == LTT_ILP32 || rSize == LTT_LP64){ + if(f->field_size != 4) + g_error("The type of the field is not unsigned int: uint32_t\n"); + else{ + uint32_t x = *(uint32_t *)(e->data + f->offset_root); + return (unsigned) (revFlag ? BREV32(x): x); + } + }else if(rSize == LTT_ILP64){ + if(f->field_size != 8) + g_error("The type of the field is not unsigned int: uint64_t\n"); + else{ + uint64_t x = *(uint64_t *)(e->data + f->offset_root); + return (unsigned) (revFlag ? BREV64(x): x); + } + } +} + +int ltt_event_get_int(ltt_event *e, ltt_field *f) +{ + ltt_arch_size rSize = e->tracefile->trace_header->arch_size; + int revFlag = e->tracefile->my_arch_endian == + e->tracefile->trace_header->arch_endian ? 0:1; + + if(f->field_type->type_class != LTT_INT) + g_error("The type of the field is not int\n"); + + if(rSize == LTT_LP32){ + if(f->field_size != 2) + g_error("The type of the field is not int: int16_t\n"); + else{ + int16_t x = *(int16_t *)(e->data + f->offset_root); + return (int) (revFlag ? BREV16(x) : x); + } + }else if(rSize == LTT_ILP32 || rSize == LTT_LP64){ + if(f->field_size != 4) + g_error("The type of the field is not int: int32_t\n"); + else{ + int32_t x = *(int32_t *)(e->data + f->offset_root); + return (int) (revFlag ? BREV32(x): x); + } + }else if(rSize == LTT_ILP64){ + if(f->field_size != 8) + g_error("The type of the field is not int: int64_t\n"); + else{ + int64_t x = *(int64_t *)(e->data + f->offset_root); + return (int) (revFlag ? BREV64(x): x); + } + } +} + +unsigned long ltt_event_get_long_unsigned(ltt_event *e, ltt_field *f) +{ + ltt_arch_size rSize = e->tracefile->trace_header->arch_size; + int revFlag = e->tracefile->my_arch_endian == + e->tracefile->trace_header->arch_endian ? 0:1; + ltt_type_enum t = f->field_type->type_class; + + if(t != LTT_UINT || t != LTT_ENUM) + g_error("The type of the field is not unsigned long\n"); + + if(rSize == LTT_LP32 || rSize == LTT_ILP32 ){ + if(f->field_size != 4) + g_error("The type of the field is not unsigned long: uint32_t\n"); + else{ + uint32_t x = *(uint32_t *)(e->data + f->offset_root); + return (unsigned long) (revFlag ? BREV32(x) : x); + } + }else if(rSize == LTT_LP64 || rSize == LTT_ILP64){ + if(f->field_size != 8) + g_error("The type of the field is not unsigned long: uint64_t\n"); + else{ + uint64_t x = *(uint64_t *)(e->data + f->offset_root); + return (unsigned long) (revFlag ? BREV64(x): x); + } + } +} + +long int ltt_event_get_long_int(ltt_event *e, ltt_field *f) +{ + ltt_arch_size rSize = e->tracefile->trace_header->arch_size; + int revFlag = e->tracefile->my_arch_endian == + e->tracefile->trace_header->arch_endian ? 0:1; + + if( f->field_type->type_class != LTT_INT) + g_error("The type of the field is not long int\n"); + + if(rSize == LTT_LP32 || rSize == LTT_ILP32 ){ + if(f->field_size != 4) + g_error("The type of the field is not long int: int32_t\n"); + else{ + int32_t x = *(int32_t *)(e->data + f->offset_root); + return (long) (revFlag ? BREV32(x) : x); + } + }else if(rSize == LTT_LP64 || rSize == LTT_ILP64){ + if(f->field_size != 8) + g_error("The type of the field is not long int: int64_t\n"); + else{ + int64_t x = *(int64_t *)(e->data + f->offset_root); + return (long) (revFlag ? BREV64(x): x); + } + } +} + +float ltt_event_get_float(ltt_event *e, ltt_field *f) +{ + int revFlag = e->tracefile->my_arch_endian == + e->tracefile->trace_header->arch_endian ? 0:1; + + if(f->field_type->type_class != LTT_FLOAT || + (f->field_type->type_class == LTT_FLOAT && f->field_size != 4)) + g_error("The type of the field is not float\n"); + + if(revFlag == 0) return *(float *)(e->data + f->offset_root); + else{ + uint32_t aInt; + memcpy((void*)&aInt, e->data + f->offset_root, 4); + aInt = ___swab32(aInt); + return *((float*)&aInt); + } +} + +double ltt_event_get_double(ltt_event *e, ltt_field *f) +{ + int revFlag = e->tracefile->my_arch_endian == + e->tracefile->trace_header->arch_endian ? 0:1; + + if(f->field_type->type_class != LTT_FLOAT || + (f->field_type->type_class == LTT_FLOAT && f->field_size != 8)) + g_error("The type of the field is not double\n"); + + if(revFlag == 0) return *(double *)(e->data + f->offset_root); + else{ + uint64_t aInt; + memcpy((void*)&aInt, e->data + f->offset_root, 8); + aInt = ___swab64(aInt); + return *((double *)&aInt); + } +} + +/***************************************************************************** + * The string obtained is only valid until the next read from + * the same tracefile. ???? + ****************************************************************************/ + +char *ltt_event_get_string(ltt_event *e, ltt_field *f) +{ + if(f->field_type->type_class != LTT_STRING) + g_error("The field contains no string\n"); + return (char*)g_strdup((char*)(e->data + f->offset_root)); +} diff --git a/ltt/branches/poly/ltt/facility.c b/ltt/branches/poly/ltt/facility.c new file mode 100644 index 00000000..ad489cae --- /dev/null +++ b/ltt/branches/poly/ltt/facility.c @@ -0,0 +1,497 @@ +#include +#include +#include + +#include "LTTTypes.h" +#include "parser.h" +#include + +/* 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;iposition;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;ilabels.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;ifields.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;iall_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;ievent_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;ikeys.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;iposition;i++){ + freeLttType((ltt_type*)(unnamed_types->array[i])); + } + sequence_dispose(unnamed_types); +} + +void freeAllFields(sequence * all_fields) +{ + int i; + for(i=0;iposition;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;ievent_number;i++){ + ev = f->events[i]; + if(strcmp(ev->name, name) == 0)break; + } + + if(i==f->event_number) return NULL; + else return ev; +} + diff --git a/ltt/branches/poly/ltt/parser.c b/ltt/branches/poly/ltt/parser.c new file mode 100644 index 00000000..2851188f --- /dev/null +++ b/ltt/branches/poly/ltt/parser.c @@ -0,0 +1,985 @@ +/* + +parser.c: Generate helper declarations and functions to trace events + from an event description file. + +Copyright (C) 2002, Xianxiu Yang +Copyright (C) 2002, Michel Dagenais +This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* This program reads the ".event" event definitions input files + specified as command line arguments and generates corresponding + ".c" and ".h" files required to trace such events in the kernel. + + The program uses a very simple tokenizer, called from a hand written + recursive descent parser to fill a data structure describing the events. + The result is a sequence of events definitions which refer to type + definitions. + + A table of named types is maintained to allow refering to types by name + when the same type is used at several places. Finally a sequence of + all types is maintained to facilitate the freeing of all type + information when the processing of an ".event" file is finished. */ + +#include +#include +#include +#include +#include + + +#include "parser.h" + + +/***************************************************************************** + *Function name + * getSize : translate from string to integer + *Input params + * in : input file handle + *Return values + * size + *****************************************************************************/ + +int getSize(parse_file *in) +{ + char *token; + + token = getToken(in); + if(in->type == NUMBER) { + if(strcmp(token,"1") == 0) return 0; + else if(strcmp(token,"2") == 0) return 1; + else if(strcmp(token,"4") == 0) return 2; + else if(strcmp(token,"8") == 0) return 3; + } + else if(in->type == NAME) { + if(strcmp(token,"short") == 0) return 4; + else if(strcmp(token,"medium") == 0) return 5; + else if(strcmp(token,"long") == 0) return 6; + } + in->error(in,"incorrect size specification"); + return -1; +} + +/***************************************************************************** + *Function name + * error_callback : print out error info + *Input params + * in : input file handle + * msg : message to be printed + ****************************************************************************/ + +void error_callback(parse_file *in, char *msg) +{ + if(in) + printf("Error in file %s, line %d: %s\n", in->name, in->lineno, msg); + else + printf("%s\n",msg); + exit(1); +} + +/***************************************************************************** + *Function name + * memAlloc : allocate memory + *Input params + * size : required memory size + *return value + * void * : pointer to allocate memory or NULL + ****************************************************************************/ + +void * memAlloc(int size) +{ + void *addr = malloc(size); + if(!addr){ + printf("Failed to allocate memory"); + exit(1); + } + return addr; +} + +/***************************************************************************** + *Function name + * allocAndCopy : allocate memory and initialize it + *Input params + * str : string to be put in memory + *return value + * char * : pointer to allocate memory or NULL + ****************************************************************************/ + +char *allocAndCopy(char *str) +{ + char *addr = (char *)memAlloc(strlen(str)+1); + strcpy(addr,str); + return addr; +} + + +/***************************************************************************** + *Function name + * parseEvent : generate event from event definition + *Input params + * in : input file handle + * ev : new event + *Output params + * ev : new event (parameters are passed to it) + ****************************************************************************/ + +void parseEvent(parse_file *in, event * ev, sequence * unnamed_types, + table * named_types) +{ + char *token; + type_descriptor *t; + + getLParenthesis(in); + token = getName(in); + ev->name = allocAndCopy(token); + getComa(in); + + token = getQuotedString(in); + ev->description = allocAndCopy(token); + + token = getToken(in); //token either is a ',' or a ')' + if(in->type == COMA) token = getName(in); + ungetToken(in); + + /* We have a possibly empty list of fields, containing struct implied */ + if((in->type == NAME && strcmp(token,"field") == 0) || + in->type == RPARENTHESIS) { + /* Insert an unnamed struct type */ + t = (type_descriptor *)memAlloc(sizeof(type_descriptor)); + t->type_name = NULL; + t->type = STRUCT; + t->fmt = NULL; + if(in->type == NAME) parseFields(in,t, unnamed_types, named_types); + else if(in->type == RPARENTHESIS) sequence_init(&(t->fields)); + sequence_push(unnamed_types,t); + ev->type = t; + } + + /* Or a complete type declaration but it must be a struct */ + else if(in->type == NAME){ + ev->type = parseType(in,NULL, unnamed_types, named_types); + if(ev->type->type != STRUCT && ev->type->type != NONE) in->error(in,"type must be a struct"); + }else in->error(in,"not a struct type"); + + getRParenthesis(in); + getSemiColon(in); +} + +/***************************************************************************** + *Function name + * parseField : get field infomation from buffer + *Input params + * in : input file handle + * t : type descriptor + ****************************************************************************/ + +void parseFields(parse_file *in, type_descriptor *t, sequence * unnamed_types, + table * named_types) +{ + char * token; + field *f; + + sequence_init(&(t->fields)); + + token = getToken(in); + while(in->type == NAME && strcmp(token,"field") == 0) { + f = (field *)memAlloc(sizeof(field)); + sequence_push(&(t->fields),f); + + getLParenthesis(in); + f->name = (char *)allocAndCopy(getName(in)); + getComa(in); + f->description = (char *)allocAndCopy(getQuotedString(in)); + getComa(in); + f->type = parseType(in,NULL, unnamed_types, named_types); + getRParenthesis(in); + + token = getToken(in); + if(in->type == COMA) token = getName(in); + else ungetToken(in); // no more fields, it must be a ')' + } + + if(in->type == NAME && strcmp(token,"field") != 0) + in->error(in,"not a field"); +} + + +/***************************************************************************** + *Function name + * parseType : get type information, type can be : + * Primitive: + * int(size,fmt); uint(size,fmt); float(size,fmt); + * string(fmt); enum(size,fmt,(label1,label2...)) + * Compound: + * array(arraySize, type); sequence(lengthSize,type) + * struct(field(name,type,description)...) + * type name: + * type(name,type) + *Input params + * in : input file handle + * inType : a type descriptor + *Return values + * type_descriptor* : a type descriptor + ****************************************************************************/ + +type_descriptor *parseType(parse_file *in, type_descriptor *inType, + sequence * unnamed_types, table * named_types) +{ + char *token, *car; + type_descriptor *t; + + if(inType == NULL) { + t = (type_descriptor *) memAlloc(sizeof(type_descriptor)); + t->type_name = NULL; + t->type = NONE; + t->fmt = NULL; + sequence_push(unnamed_types,t); + } + else t = inType; + + token = getName(in); + + if(strcmp(token,"struct") == 0) { + t->type = STRUCT; + getLParenthesis(in); + parseFields(in,t, unnamed_types, named_types); + getRParenthesis(in); + } + else if(strcmp(token,"array") == 0) { + t->type = ARRAY; + getLParenthesis(in); + t->size = getNumber(in); + getComa(in); + t->nested_type = parseType(in,NULL, unnamed_types, named_types); + getRParenthesis(in); + } + else if(strcmp(token,"sequence") == 0) { + t->type = SEQUENCE; + getLParenthesis(in); + t->size = getSize(in); + getComa(in); + t->nested_type = parseType(in,NULL, unnamed_types, named_types); + getRParenthesis(in); + } + else if(strcmp(token,"enum") == 0) { + t->type = ENUM; + sequence_init(&(t->labels)); + getLParenthesis(in); + t->size = getSize(in); + getComa(in); + token = getToken(in); + if(in->type == QUOTEDSTRING){ + t->fmt = allocAndCopy(token); + getComa(in); + }else ungetToken(in); + getLParenthesis(in); + + token = getToken(in); + while(in->type != RPARENTHESIS) { + if(in->type != NAME) in->error(in,"Name token was expected"); + car = allocAndCopy(token); + token = getToken(in); + if(in->type == COMA){ + sequence_push(&(t->labels),allocAndCopy(car)); + token = getName(in); + }else if(in->type == EQUAL){ //label followed by '=' and a number, e.x. label1 = 1, + car = appendString(car, token); + token = getToken(in); + if(in->type != NUMBER) in->error(in,"Number token was expected"); + car = appendString(car, token); + sequence_push(&(t->labels),allocAndCopy(car)); + token = getToken(in); + if(in->type == COMA) token = getName(in); + else ungetToken(in); + }else{ + sequence_push(&(t->labels),allocAndCopy(car)); + ungetToken(in); + } + } + getRParenthesis(in); + getRParenthesis(in); + } + else if(strcmp(token,"int") == 0) { + t->type = INT; + getLParenthesis(in); + t->size = getSize(in); + token = getToken(in); + if(in->type == COMA) { + token = getQuotedString(in); + t->fmt = allocAndCopy(token); + } + else ungetToken(in); + getRParenthesis(in); + } + else if(strcmp(token,"uint") == 0) { + t->type = UINT; + getLParenthesis(in); + t->size = getSize(in); + token = getToken(in); + if(in->type == COMA) { + token = getQuotedString(in); + t->fmt = allocAndCopy(token); + } + else ungetToken(in); + getRParenthesis(in); + } + else if(strcmp(token,"float") == 0) { + t->type = FLOAT; + getLParenthesis(in); + t->size = getSize(in); + token = getToken(in); + if(in->type == COMA) { + token = getQuotedString(in); + t->fmt = allocAndCopy(token); + } + else ungetToken(in); + getRParenthesis(in); + } + else if(strcmp(token,"string") == 0) { + t->type = STRING; + getLParenthesis(in); + token = getToken(in); + if(in->type == QUOTEDSTRING) t->fmt = allocAndCopy(token); + else ungetToken(in); + getRParenthesis(in); + } + else { + /* Must be a named type */ + if(inType != NULL) + in->error(in,"Named type cannot refer to a named type"); + else { + free(t); + sequence_pop(unnamed_types); + return(find_named_type(token, named_types)); + } + } + + return t; +} + +/***************************************************************************** + *Function name + * find_named_type : find a named type from hash table + *Input params + * name : type name + *Return values + * type_descriptor * : a type descriptor + *****************************************************************************/ + +type_descriptor * find_named_type(char *name, table * named_types) +{ + type_descriptor *t; + + t = table_find(named_types,name); + if(t == NULL) { + t = (type_descriptor *)memAlloc(sizeof(type_descriptor)); + t->type_name = allocAndCopy(name); + t->type = NONE; + t->fmt = NULL; + table_insert(named_types,allocAndCopy(name),t); + } + return t; +} + +/***************************************************************************** + *Function name + * parseTypeDefinition : get type information from type definition + *Input params + * in : input file handle + *****************************************************************************/ + +void parseTypeDefinition(parse_file * in, sequence * unnamed_types, + table * named_types) +{ + char *token; + type_descriptor *t; + + getLParenthesis(in); + token = getName(in); + t = find_named_type(token, named_types); + getComa(in); + + if(t->type != NONE) in->error(in,"redefinition of named type"); + parseType(in,t, unnamed_types, named_types); + + getRParenthesis(in); + getSemiColon(in); +} + +/************************************************************************** + * Function : + * getComa, getName, getNumber, getLParenthesis, getRParenthesis, getEqual + * Description : + * Read a token from the input file, check its type, return it scontent. + * + * Parameters : + * in , input file handle. + * + * Return values : + * address of token content. + * + **************************************************************************/ + +char *getName(parse_file * in) +{ + char *token; + + token = getToken(in); + if(in->type != NAME) in->error(in,"Name token was expected"); + return token; +} + +int getNumber(parse_file * in) +{ + char *token; + + token = getToken(in); + if(in->type != NUMBER) in->error(in, "Number token was expected"); + return atoi(token); +} + +char *getComa(parse_file * in) +{ + char *token; + + token = getToken(in); + if(in->type != COMA) in->error(in, "Coma token was expected"); + return token; +} + +char *getLParenthesis(parse_file * in) +{ + char *token; + + token = getToken(in); + if(in->type != LPARENTHESIS) in->error(in, "Left parenthesis was expected"); + return token; +} + +char *getRParenthesis(parse_file * in) +{ + char *token; + + token = getToken(in); + if(in->type != RPARENTHESIS) in->error(in, "Right parenthesis was expected"); + return token; +} + +char *getQuotedString(parse_file * in) +{ + char *token; + + token = getToken(in); + if(in->type != QUOTEDSTRING) in->error(in, "quoted string was expected"); + return token; +} + +char * getSemiColon(parse_file *in) +{ + char *token; + + token = getToken(in); + if(in->type != SEMICOLON) in->error(in, "semicolon was expected"); + return token; +} + +char * getEqual(parse_file *in) +{ + char *token; + + token = getToken(in); + if(in->type != EQUAL) in->error(in, "equal was expected"); + return token; +} + +/****************************************************************** + * Function : + * getToken, ungetToken + * Description : + * Read a token from the input file and return its type and content. + * Line numbers are accounted for and whitespace/comments are skipped. + * + * Parameters : + * in, input file handle. + * + * Return values : + * address of token content. + * + ******************************************************************/ + +void ungetToken(parse_file * in) +{ + in->unget = 1; +} + +char *getToken(parse_file * in) +{ + FILE *fp = in->fp; + char car, car1; + int pos = 0, escaped; + + if(in->unget == 1) { + in->unget = 0; + return in->buffer; + } + + /* skip whitespace and comments */ + + while((car = getc(fp)) != EOF) { + if(car == '/') { + car1 = getc(fp); + if(car1 == '*') skipComment(in); + else if(car1 == '/') skipEOL(in); + else { + car1 = ungetc(car1,fp); + break; + } + } + else if(car == '\n') in->lineno++; + else if(!isspace(car)) break; + } + + switch(car) { + case EOF: + in->type = ENDFILE; + break; + case ',': + in->type = COMA; + in->buffer[pos] = car; + pos++; + break; + case '(': + in->type = LPARENTHESIS; + in->buffer[pos] = car; + pos++; + break; + case ')': + in->type = RPARENTHESIS; + in->buffer[pos] = car; + pos++; + break; + case ';': + in->type = SEMICOLON; + in->buffer[pos] = car; + pos++; + break; + case '=': + in->type = EQUAL; + in->buffer[pos] = car; + pos++; + break; + case '"': + escaped = 0; + while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) { + if(car == '\\' && escaped == 0) { + in->buffer[pos] = car; + pos++; + escaped = 1; + continue; + } + if(car == '"' && escaped == 0) break; + if(car == '\n' && escaped == 0) { + in->error(in, "non escaped newline inside quoted string"); + } + if(car == '\n') in->lineno++; + in->buffer[pos] = car; + pos++; + escaped = 0; + } + if(car == EOF) in->error(in,"no ending quotemark"); + if(pos == BUFFER_SIZE) in->error(in, "quoted string token too large"); + in->type = QUOTEDSTRING; + break; + default: + if(isdigit(car)) { + in->buffer[pos] = car; + pos++; + while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) { + if(!isdigit(car)) { + ungetc(car,fp); + break; + } + in->buffer[pos] = car; + pos++; + } + if(car == EOF) ungetc(car,fp); + if(pos == BUFFER_SIZE) in->error(in, "number token too large"); + in->type = NUMBER; + } + else if(isalpha(car)) { + in->buffer[0] = car; + pos = 1; + while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) { + if(!isalnum(car)) { + ungetc(car,fp); + break; + } + in->buffer[pos] = car; + pos++; + } + if(car == EOF) ungetc(car,fp); + if(pos == BUFFER_SIZE) in->error(in, "name token too large"); + in->type = NAME; + } + else in->error(in, "invalid character, unrecognized token"); + } + in->buffer[pos] = 0; + return in->buffer; +} + +void skipComment(parse_file * in) +{ + char car; + while((car = getc(in->fp)) != EOF) { + if(car == '\n') in->lineno++; + else if(car == '*') { + car = getc(in->fp); + if(car ==EOF) break; + if(car == '/') return; + ungetc(car,in->fp); + } + } + if(car == EOF) in->error(in,"comment begining with '/*' has no ending '*/'"); +} + +void skipEOL(parse_file * in) +{ + char car; + while((car = getc(in->fp)) != EOF) { + if(car == '\n') { + ungetc(car,in->fp); + break; + } + } + if(car == EOF)ungetc(car, in->fp); +} + +int isalpha(char c) +{ + int i,j; + if(c == '_')return 1; + i = c - 'a'; + j = c - 'A'; + if((i>=0 && i<26) || (j>=0 && j<26)) return 1; + return 0; +} + +int isalnum(char c) +{ + return (isalpha(c) || isdigit(c)); +} + +/***************************************************************************** + *Function name + * checkNamedTypesImplemented : check if all named types have definition + ****************************************************************************/ + +void checkNamedTypesImplemented(table * named_types) +{ + type_descriptor *t; + int pos; + char str[256]; + + for(pos = 0 ; pos < named_types->values.position; pos++) { + t = (type_descriptor *) named_types->values.array[pos]; + if(t->type == NONE){ + sprintf(str,"named type '%s' has no definition",(char*)named_types->keys.array[pos]); + error_callback(NULL,str); + } + } +} + + +/***************************************************************************** + *Function name + * generateChecksum : generate checksum for the facility + *Input Params + * facName : name of facility + *Output Params + * checksum : checksum for the facility + ****************************************************************************/ + +void generateChecksum( char* facName, unsigned long * checksum, sequence * events) +{ + unsigned long crc ; + int pos, nestedStruct; + event * ev; + char str[256]; + + crc = crc32(facName); + for(pos = 0; pos < events->position; pos++){ + ev = (event *)(events->array[pos]); + ev->nested = 0; //by default, event has no nested struct + crc = partial_crc32(ev->name,crc); + nestedStruct = 0; + if(ev->type->type != STRUCT){ + sprintf(str,"event '%s' has a type other than STRUCT",ev->name); + error_callback(NULL, str); + } + crc = getTypeChecksum(crc, ev->type,&nestedStruct); + if(nestedStruct ) ev->nested = 1; + } + *checksum = crc; +} + +/***************************************************************************** + *Function name + * getTypeChecksum : generate checksum by type info + *Input Params + * crc : checksum generated so far + * type : type descriptor containing type info + *Return value + * unsigned long : checksum + *****************************************************************************/ + +unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor * type, + int * nestedStruct) +{ + unsigned long crc = aCrc; + char * str = NULL, buf[16]; + int flag = 0, pos, max, min; + field * fld; + data_type dt; + + switch(type->type){ + case INT: + str = intOutputTypes[type->size]; + break; + case UINT: + str = uintOutputTypes[type->size]; + break; + case FLOAT: + str = floatOutputTypes[type->size]; + break; + case STRING: + str = allocAndCopy("string"); + flag = 1; + break; + case ENUM: + str = appendString("enum ", uintOutputTypes[type->size]); + flag = 1; + break; + case ARRAY: + sprintf(buf,"%d\0",type->size); + str = appendString("array ",buf); + flag = 1; + break; + case SEQUENCE: + sprintf(buf,"%d\0",type->size); + str = appendString("sequence ",buf); + flag = 1; + break; + case STRUCT: + str = allocAndCopy("struct"); + flag = 1; + break; + default: + error_callback(NULL, "named type has no definition"); + break; + } + + crc = partial_crc32(str,crc); + if(flag) free(str); + + if(type->fmt) crc = partial_crc32(type->fmt,crc); + + if(type->type == ARRAY || type->type == SEQUENCE){ + dt = type->nested_type->type; + if(dt == ARRAY || dt == SEQUENCE || dt == STRUCT) *nestedStruct += 1; + crc = getTypeChecksum(crc,type->nested_type,nestedStruct); + }else if(type->type == STRUCT){ + if(type->fields.position != 0){//not a empty struct + max = 0; + for(pos =0; pos < type->fields.position; pos++){ + min = 0; + fld = (field *) type->fields.array[pos]; + crc = partial_crc32(fld->name,crc); + if(fld->type->type == STRUCT) min++; + crc = getTypeChecksum(crc, fld->type,&min); + if(min>max) max = min; + } + *nestedStruct += max; + } + }else if(type->type == ENUM){ + for(pos = 0; pos < type->labels.position; pos++) + crc = partial_crc32((char*)type->labels.array[pos],crc); + } + + return crc; +} + + +/* Event type descriptors */ +void freeType(type_descriptor * tp) +{ + int pos2; + field *f; + + if(tp->fmt != NULL) free(tp->fmt); + if(tp->type == ENUM) { + for(pos2 = 0; pos2 < tp->labels.position; pos2++) { + free(tp->labels.array[pos2]); + } + sequence_dispose(&(tp->labels)); + } + if(tp->type == STRUCT) { + for(pos2 = 0; pos2 < tp->fields.position; pos2++) { + f = (field *) tp->fields.array[pos2]; + free(f->name); + free(f->description); + free(f); + } + sequence_dispose(&(tp->fields)); + } +} + +void freeNamedType(table * t) +{ + int pos; + type_descriptor * td; + + for(pos = 0 ; pos < t->keys.position; pos++) { + free((char *)t->keys.array[pos]); + td = (type_descriptor*)t->values.array[pos]; + freeType(td); + free(td); + } +} + +void freeTypes(sequence *t) +{ + int pos, pos2; + type_descriptor *tp; + field *f; + + for(pos = 0 ; pos < t->position; pos++) { + tp = (type_descriptor *)t->array[pos]; + freeType(tp); + free(tp); + } +} + +void freeEvents(sequence *t) +{ + int pos; + event *ev; + + for(pos = 0 ; pos < t->position; pos++) { + ev = (event *) t->array[pos]; + free(ev->name); + free(ev->description); + free(ev); + } + +} + + +/* Extensible array */ + +void sequence_init(sequence *t) +{ + t->size = 10; + t->position = 0; + t->array = (void **)memAlloc(t->size * sizeof(void *)); +} + +void sequence_dispose(sequence *t) +{ + t->size = 0; + free(t->array); + t->array = NULL; +} + +void sequence_push(sequence *t, void *elem) +{ + void **tmp; + + if(t->position >= t->size) { + tmp = t->array; + t->array = (void **)memAlloc(t->size * 2 * sizeof(void *)); + memcpy(t->array, tmp, t->size * sizeof(void *)); + t->size = t->size * 2; + free(tmp); + } + t->array[t->position] = elem; + t->position++; +} + +void *sequence_pop(sequence *t) +{ + return t->array[t->position--]; +} + + +/* Hash table API, implementation is just linear search for now */ + +void table_init(table *t) +{ + sequence_init(&(t->keys)); + sequence_init(&(t->values)); +} + +void table_dispose(table *t) +{ + sequence_dispose(&(t->keys)); + sequence_dispose(&(t->values)); +} + +void table_insert(table *t, char *key, void *value) +{ + sequence_push(&(t->keys),key); + sequence_push(&(t->values),value); +} + +void *table_find(table *t, char *key) +{ + int pos; + for(pos = 0 ; pos < t->keys.position; pos++) { + if(strcmp((char *)key,(char *)t->keys.array[pos]) == 0) + return(t->values.array[pos]); + } + return NULL; +} + +void table_insert_int(table *t, int *key, void *value) +{ + sequence_push(&(t->keys),key); + sequence_push(&(t->values),value); +} + +void *table_find_int(table *t, int *key) +{ + int pos; + for(pos = 0 ; pos < t->keys.position; pos++) { + if(*key == *(int *)t->keys.array[pos]) + return(t->values.array[pos]); + } + return NULL; +} + + +/* Concatenate strings */ + +char *appendString(char *s, char *suffix) +{ + char *tmp; + + tmp = (char *)memAlloc(strlen(s) + strlen(suffix) + 1); + strcpy(tmp,s); + strcat(tmp,suffix); + return tmp; +} + + diff --git a/ltt/branches/poly/ltt/parser.h b/ltt/branches/poly/ltt/parser.h new file mode 100644 index 00000000..5e0c421b --- /dev/null +++ b/ltt/branches/poly/ltt/parser.h @@ -0,0 +1,189 @@ +#ifndef PARSER_H +#define PARSER_H + +/* Extensible array container */ + +typedef struct _sequence { + int size; + int position; + void **array; +} sequence; + +void sequence_init(sequence *t); +void sequence_dispose(sequence *t); +void sequence_push(sequence *t, void *elem); +void *sequence_pop(sequence *t); + + +/* Hash table */ + +typedef struct _table { + sequence keys; + sequence values; +} table; + +void table_init(table *t); +void table_dispose(table *t); +void table_insert(table *t, char *key, void *value); +void *table_find(table *t, char *key); +void table_insert_int(table *t, int *key, void *value); +void *table_find_int(table *t, int *key); + + +/* Token types */ + +typedef enum _token_type { + ENDFILE, + COMA, + LPARENTHESIS, + RPARENTHESIS, + SEMICOLON, + EQUAL, + QUOTEDSTRING, + NUMBER, + NAME +} token_type; + + +/* State associated with a file being parsed */ +typedef struct _parse_file { + char *name; + FILE * fp; + int lineno; + char *buffer; + token_type type; + int unget; + void (*error) (struct _parse_file *, char *); +} parse_file; + +void ungetToken(parse_file * in); +char *getToken(parse_file *in); +char *getComa(parse_file *in); +char *getLParenthesis(parse_file *in); +char *getRParenthesis(parse_file *in); +char *getSemiColon(parse_file *in); +char *getQuotedString(parse_file *in); +char *getName(parse_file *in); +int getNumber(parse_file *in); +char * getEqual(parse_file *in); + +void skipComment(parse_file * in); +void skipEOL(parse_file * in); +int isalpha(char car); +int isalnum(char car); + +/* Some constants */ + +static const int BUFFER_SIZE = 1024; + + +/* Events data types */ + +typedef enum _data_type { + INT, + UINT, + FLOAT, + STRING, + ENUM, + ARRAY, + SEQUENCE, + STRUCT, + NONE +} data_type; + + +/* Event type descriptors */ + +typedef struct _type_descriptor { + char * type_name; //used for named type + data_type type; + char *fmt; + int size; + sequence labels; // for enumeration + sequence fields; // for structure + struct _type_descriptor *nested_type; // for array and sequence +} type_descriptor; + + +/* Fields within types */ + +typedef struct _field{ + char *name; + char *description; + type_descriptor *type; +} field; + + +/* Events definitions */ + +typedef struct _event { + char *name; + char *description; + type_descriptor *type; + int nested; +} event; + +int getSize(parse_file *in); +unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor * type, int * nestedStruct); + +void parseEvent(parse_file *in, event *ev, sequence * unnamed_types, table * named_types); +void parseTypeDefinition(parse_file *in, sequence * unnamed_types, table * named_types); +type_descriptor *parseType(parse_file *in, type_descriptor *t, sequence * unnamed_types, table * named_types); +void parseFields(parse_file *in, type_descriptor *t, sequence * unnamed_types, table * named_types); +void checkNamedTypesImplemented(table * namedTypes); +type_descriptor * find_named_type(char *name, table * named_types); +void generateChecksum(char * facName, unsigned long * checksum, sequence * events); + + + +static char *intOutputTypes[] = { + "int8_t", "int16_t", "int32_t", "int64_t", "short int", "int", "long int" }; + +static char *uintOutputTypes[] = { + "uint8_t", "uint16_t", "uint32_t", "uint64_t", "unsigned short int", + "unsigned int", "unsigned long int" }; + +static char *floatOutputTypes[] = { + "undef", "undef", "float", "double", "undef", "float", "double" }; + + +/* Dynamic memory allocation and freeing */ + +void * memAlloc(int size); +char *allocAndCopy(char * str); +char *appendString(char *s, char *suffix); +void freeTypes(sequence *t); +void freeType(type_descriptor * td); +void freeEvents(sequence *t); +void freeNamedType(table * t); +void error_callback(parse_file *in, char *msg); + + +//checksum part +static const unsigned int crctab32[] = +{ +#include "crc32.tab" +}; + +static inline unsigned long +partial_crc32_one(unsigned char c, unsigned long crc) +{ + return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8); +} + +static inline unsigned long +partial_crc32(const char *s, unsigned long crc) +{ + while (*s) + crc = partial_crc32_one(*s++, crc); + return crc; +} + +static inline unsigned long +crc32(const char *s) +{ + return partial_crc32(s, 0xffffffff) ^ 0xffffffff; +} + + +#endif // PARSER_H diff --git a/ltt/branches/poly/ltt/tracefile.c b/ltt/branches/poly/ltt/tracefile.c new file mode 100644 index 00000000..f16124f6 --- /dev/null +++ b/ltt/branches/poly/ltt/tracefile.c @@ -0,0 +1,993 @@ +#include +#include +#include +#include +#include + +#include "LTTTypes.h" +#include "parser.h" +#include + +#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:t1t2 */ +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; ieventtype_event_id, i); + ((ptr_wrap*)tmpPtr)->ptr = NULL; + } + } + + //initialize the elements with the eventtypes belonging to the facility + for(i=0; ievent_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; ievent_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;ichild[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;ichild[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;ichild[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;ichild[i],evD+offset2); + offset1 += size; + offset2 += size; + } + size = offset2; + }else size = fld->field_size; + } + + fld->offset_root = offsetRoot; + fld->offset_parent = offsetParent; + if(!evD){ + fld->fixed_root = (offsetRoot==-1) ? 0 : 1; + fld->fixed_parent = (offsetParent==-1) ? 0 : 1; + } + fld->field_size = size; + + return size; +} + +/***************************************************************************** + *Function name + * timecmp : compare two time + *Input params + * t1 : first time + * t2 : second time + *Return value + * int : 0: t1 == t2; -1: t1 < t2; 1: t1 > t2 + ****************************************************************************/ + +int timecmp(ltt_time * t1, ltt_time * t2) +{ + ltt_time T; + TimeSub(T, *t1, *t2); + if(T.tv_sec == 0 && T.tv_nsec == 0) return 0; + else if(T.tv_sec > 0 || (T.tv_sec==0 && T.tv_nsec > 0)) return 1; + else return -1; +} + +/***************************************************************************** + *Function name + * getIntNumber : get an integer number + *Input params + * size : the size of the integer + * evD : the event data + *Return value + * int : an integer + ****************************************************************************/ + +int getIntNumber(int size, void *evD) +{ + int64_t i; + if(size == 1) i = *(int8_t *)evD; + else if(size == 2) i = *(int16_t *)evD; + else if(size == 4) i = *(int32_t *)evD; + else if(size == 8) i = *(int64_t *)evD; + + return (int) i; +} + +/***************************************************************************** + *Function name + * getDataEndianType : get the data type size and endian type of the local + * machine + *Input params + * size : size of data type + * endian : endian type, little or big + ****************************************************************************/ + +void getDataEndianType(ltt_arch_size * size, ltt_arch_endian * endian) +{ + int i = 1; + char c = (char) i; + int sizeInt=sizeof(int), sizeLong=sizeof(long), sizePointer=sizeof(void *); + + if(c == 1) *endian = LTT_LITTLE_ENDIAN; + else *endian = LTT_BIG_ENDIAN; + + if(sizeInt == 2 && sizeLong == 4 && sizePointer == 4) + *size = LTT_LP32; + else if(sizeInt == 4 && sizeLong == 4 && sizePointer == 4) + *size = LTT_ILP32; + else if(sizeInt == 4 && sizeLong == 8 && sizePointer == 8) + *size = LTT_LP64; + else if(sizeInt == 8 && sizeLong == 8 && sizePointer == 8) + *size = LTT_ILP64; + else *size = LTT_UNKNOWN; +} + diff --git a/ltt/branches/poly/ltt/type.c b/ltt/branches/poly/ltt/type.c new file mode 100644 index 00000000..98150772 --- /dev/null +++ b/ltt/branches/poly/ltt/type.c @@ -0,0 +1,253 @@ +#include + +#include "LTTTypes.h" +#include "parser.h" +#include + +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; +} +