Logo Search packages:      
Sourcecode: iverilog version File versions  Download package

lxt_write.c

/*
 * Copyright (c) 2001-7 Tony Bybell.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include <config.h>
#include "lxt_write.h"

/*
 * in-place sort to keep chained facs from migrating...
 */
static void wave_mergesort(struct lt_symbol **a, struct lt_symbol **b, int lo, int hi)
{
int i, j, k;

if (lo<hi)
      {
        int mid=(lo+hi)/2;

        wave_mergesort(a, b, lo, mid);
        wave_mergesort(a, b, mid+1, hi);

      i=0; j=lo;
      while (j<=mid)
            {
            b[i++]=a[j++];
            }

      i=0; k=lo;
      while ((k<j)&&(j<=hi))
            {
            if (strcmp(b[i]->name, a[j]->name) <= 0)
                  {
                        a[k++]=b[i++];
                  }
                  else
                  {
                        a[k++]=a[j++];
                  }
            }

      while (k<j)
            {
            a[k++]=b[i++];
            }
      }
}

static void wave_msort(struct lt_symbol **a, int num)
{
struct lt_symbol **b = malloc(((num/2)+1) * sizeof(struct lt_symbol *));

wave_mergesort(a, b, 0, num-1);

free(b);
}

/************************ splay ************************/

static int dslxt_success;

static dslxt_Tree * dslxt_splay (char *i, dslxt_Tree * t) {
/* Simple top down splay, not requiring i to be in the tree t.  */
/* What it does is described above.                             */
    dslxt_Tree N, *l, *r, *y;
    int dir;

    dslxt_success = 0;

    if (t == NULL) return t;
    N.left = N.right = NULL;
    l = r = &N;

    for (;;) {
      dir = strcmp(i, t->item);
      if (dir < 0) {
          if (t->left == NULL) break;
          if (strcmp(i, t->left->item)<0) {
            y = t->left;                           /* rotate right */
            t->left = y->right;
            y->right = t;
            t = y;
            if (t->left == NULL) break;
          }
          r->left = t;                               /* link right */
          r = t;
          t = t->left;
      } else if (dir > 0) {
          if (t->right == NULL) break;
          if (strcmp(i, t->right->item)>0) {
            y = t->right;                          /* rotate left */
            t->right = y->left;
            y->left = t;
            t = y;
            if (t->right == NULL) break;
          }
          l->right = t;                              /* link left */
          l = t;
          t = t->right;
      } else {
          dslxt_success=1;
          break;
      }
    }
    l->right = t->left;                                /* assemble */
    r->left = t->right;
    t->left = N.right;
    t->right = N.left;
    return t;
}


static dslxt_Tree * dslxt_insert(char *i, dslxt_Tree * t, unsigned int val) {
/* Insert i into the tree t, unless it's already there.    */
/* Return a pointer to the resulting tree.                 */
    dslxt_Tree * n;
    int dir;
    
    n = (dslxt_Tree *) calloc (1, sizeof (dslxt_Tree));
    if (n == NULL) {
      fprintf(stderr, "dslxt_insert: ran out of memory, exiting.\n");
      exit(255);
    }
    n->item = i;
    n->val  = val;
    if (t == NULL) {
      n->left = n->right = NULL;
      return n;
    }
    t = dslxt_splay(i,t);
    dir = strcmp(i,t->item);
    if (dir<0) {
      n->left = t->left;
      n->right = t;
      t->left = NULL;
      return n;
    } else if (dir>0) {
      n->right = t->right;
      n->left = t;
      t->right = NULL;
      return n;
    } else { /* We get here if it's already in the tree */
             /* Don't add it again                      */
      free(n);
      return t;
    }
}

#if 0
/* unused for now but delete is here for completeness   */
static dslxt_Tree * dslxt_delete(char *i, dslxt_Tree * t) {
/* Deletes i from the tree if it's there.               */
/* Return a pointer to the resulting tree.              */
    dslxt_Tree * x;
    if (t==NULL) return NULL;
    t = dslxt_splay(i,t);
    if (!strcmp(i, t->item)) {               /* found it */
      if (t->left == NULL) {
          x = t->right;
      } else {
          x = dslxt_splay(i, t->left);
          x->right = t->right;
      }
      free(t);
      return x;
    }
    return t;                         /* It wasn't there */
}
#endif

/************************ splay ************************/

/*
 * functions which emit various big endian
 * data to a file
 */ 
static int lt_emit_u8(struct lt_trace *lt, int value)
{
unsigned char buf[1];
int nmemb;

buf[0] = value & 0xff;
nmemb=fwrite(buf, sizeof(char), 1, lt->handle);
lt->position+=nmemb;
return(nmemb);
}


static int lt_emit_u16(struct lt_trace *lt, int value)
{
unsigned char buf[2];
int nmemb;

buf[0] = (value>>8) & 0xff;
buf[1] = value & 0xff;
nmemb = fwrite(buf, sizeof(char), 2, lt->handle);
lt->position+=nmemb;
return(nmemb);
}


static int lt_emit_u24(struct lt_trace *lt, int value)
{
unsigned char buf[3];
int nmemb;

buf[0] = (value>>16) & 0xff;
buf[1] = (value>>8) & 0xff;
buf[2] = value & 0xff;
nmemb=fwrite(buf, sizeof(char), 3, lt->handle);
lt->position+=nmemb;
return(nmemb);
}


static int lt_emit_u32(struct lt_trace *lt, int value)
{
unsigned char buf[4];
int nmemb;

buf[0] = (value>>24) & 0xff;
buf[1] = (value>>16) & 0xff;
buf[2] = (value>>8) & 0xff;
buf[3] = value & 0xff;
nmemb=fwrite(buf, sizeof(char), 4, lt->handle);
lt->position+=nmemb;
return(nmemb);
}


static int lt_emit_u64(struct lt_trace *lt, int valueh, int valuel)
{
int rc;

if((rc=lt_emit_u32(lt, valueh)))
      {
      rc=lt_emit_u32(lt, valuel);
      }

return(rc);
}


static int lt_emit_double(struct lt_trace *lt, double value)
{
int nmemb;

nmemb=fwrite(&value, sizeof(char), sizeof(double)/sizeof(char), lt->handle);
lt->position+=nmemb;
return(nmemb);
}


static int lt_emit_string(struct lt_trace *lt, char *value)
{
int rc=1;
do  
      {
        rc&=lt_emit_u8(lt, *value);
        } while(*(value++));
return(rc);
}


/*
 * gzfunctions which emit various big endian
 * data to a file.  (lt->position needs to be
 * fixed up on gzclose so the tables don't
 * get out of sync!)
 */ 
static int lt_emit_u8z(struct lt_trace *lt, int value)
{
unsigned char buf[1];
int nmemb;

buf[0] = value & 0xff;
nmemb=gzwrite(lt->zhandle, buf, 1);
lt->zpackcount++;
lt->position++;
return(nmemb);
}


static int lt_emit_u16z(struct lt_trace *lt, int value)
{
unsigned char buf[2];
int nmemb;

buf[0] = (value>>8) & 0xff;
buf[1] = value & 0xff;
nmemb = gzwrite(lt->zhandle, buf, 2);
lt->zpackcount+=2;
lt->position+=2;
return(nmemb);
}


static int lt_emit_u24z(struct lt_trace *lt, int value)
{
unsigned char buf[3];
int nmemb;

buf[0] = (value>>16) & 0xff;
buf[1] = (value>>8) & 0xff;
buf[2] = value & 0xff;
nmemb=gzwrite(lt->zhandle, buf, 3);
lt->zpackcount+=3;
lt->position+=3;
return(nmemb);
}


static int lt_emit_u32z(struct lt_trace *lt, int value)
{
unsigned char buf[4];
int nmemb;

buf[0] = (value>>24) & 0xff;
buf[1] = (value>>16) & 0xff;
buf[2] = (value>>8) & 0xff;
buf[3] = value & 0xff;
nmemb=gzwrite(lt->zhandle, buf, 4);

lt->zpackcount+=4;
lt->position+=4;
return(nmemb);
}


static int lt_emit_u64z(struct lt_trace *lt, int valueh, int valuel)
{
int rc;

if((rc=lt_emit_u32z(lt, valueh)))
      {
      rc=lt_emit_u32z(lt, valuel);
      }

return(rc);
}


static int lt_emit_doublez(struct lt_trace *lt, double value)
{
int nmemb;

nmemb=gzwrite(lt->zhandle, &value, sizeof(double)/sizeof(char));
lt->zpackcount+=(sizeof(double)/sizeof(char));
lt->position+=(sizeof(double)/sizeof(char));;
return(nmemb);
}


static int lt_emit_stringz(struct lt_trace *lt, char *value)
{
int rc=1;
do  
      {
        rc&=lt_emit_u8z(lt, *value);
        } while(*(value++));
return(rc);
}

/*
 * bz2functions which emit various big endian
 * data to a file.  (lt->position needs to be
 * fixed up on BZ2_bzclose so the tables don't
 * get out of sync!)
 */ 
static int lt_emit_u8bz(struct lt_trace *lt, int value)
{
unsigned char buf[1];
int nmemb;

buf[0] = value & 0xff;
nmemb=BZ2_bzwrite(lt->zhandle, buf, 1);
lt->zpackcount++;
lt->position++;
return(nmemb);
}


static int lt_emit_u16bz(struct lt_trace *lt, int value)
{
unsigned char buf[2];
int nmemb;

buf[0] = (value>>8) & 0xff;
buf[1] = value & 0xff;
nmemb = BZ2_bzwrite(lt->zhandle, buf, 2);
lt->zpackcount+=2;
lt->position+=2;
return(nmemb);
}


static int lt_emit_u24bz(struct lt_trace *lt, int value)
{
unsigned char buf[3];
int nmemb;

buf[0] = (value>>16) & 0xff;
buf[1] = (value>>8) & 0xff;
buf[2] = value & 0xff;
nmemb=BZ2_bzwrite(lt->zhandle, buf, 3);
lt->zpackcount+=3;
lt->position+=3;
return(nmemb);
}


static int lt_emit_u32bz(struct lt_trace *lt, int value)
{
unsigned char buf[4];
int nmemb;

buf[0] = (value>>24) & 0xff;
buf[1] = (value>>16) & 0xff;
buf[2] = (value>>8) & 0xff;
buf[3] = value & 0xff;
nmemb=BZ2_bzwrite(lt->zhandle, buf, 4);

lt->zpackcount+=4;
lt->position+=4;
return(nmemb);
}


static int lt_emit_u64bz(struct lt_trace *lt, int valueh, int valuel)
{
int rc;

if((rc=lt_emit_u32bz(lt, valueh)))
      {
      rc=lt_emit_u32bz(lt, valuel);
      }

return(rc);
}


static int lt_emit_doublebz(struct lt_trace *lt, double value)
{
int nmemb;

nmemb=BZ2_bzwrite(lt->zhandle, &value, sizeof(double)/sizeof(char));
lt->zpackcount+=(sizeof(double)/sizeof(char));
lt->position+=(sizeof(double)/sizeof(char));;
return(nmemb);
}


static int lt_emit_stringbz(struct lt_trace *lt, char *value)
{
int rc=1;
do  
      {
        rc&=lt_emit_u8bz(lt, *value);
        } while(*(value++));
return(rc);
}


/*
 * switch between compression modes above
 */
static void lt_set_zmode(struct lt_trace *lt, int mode)
{
switch(mode)
      {
      case LT_ZMODE_NONE:
      lt->lt_emit_u8 = lt_emit_u8;
      lt->lt_emit_u16 = lt_emit_u16;
      lt->lt_emit_u24 = lt_emit_u24;
      lt->lt_emit_u32 = lt_emit_u32;
      lt->lt_emit_u64 = lt_emit_u64;
      lt->lt_emit_double = lt_emit_double;
      lt->lt_emit_string = lt_emit_string;
      break;

      case LT_ZMODE_GZIP:
      lt->lt_emit_u8 = lt_emit_u8z;
      lt->lt_emit_u16 = lt_emit_u16z;
      lt->lt_emit_u24 = lt_emit_u24z;
      lt->lt_emit_u32 = lt_emit_u32z;
      lt->lt_emit_u64 = lt_emit_u64z;
      lt->lt_emit_double = lt_emit_doublez;
      lt->lt_emit_string = lt_emit_stringz;
      break;

      case LT_ZMODE_BZIP2:
      lt->lt_emit_u8 = lt_emit_u8bz;
      lt->lt_emit_u16 = lt_emit_u16bz;
      lt->lt_emit_u24 = lt_emit_u24bz;
      lt->lt_emit_u32 = lt_emit_u32bz;
      lt->lt_emit_u64 = lt_emit_u64bz;
      lt->lt_emit_double = lt_emit_doublebz;
      lt->lt_emit_string = lt_emit_stringbz;
      break;
      }
}


/*
 * hash/symtable manipulation
 */
static int lt_hash(const char *s)
{
const char *p;
char ch;
unsigned int h=0, h2=0, pos=0, g;
for(p=s;*p;p++)
        {
      ch=*p;
      h2<<=3;
      h2-=((unsigned int)ch+(pos++));           /* this handles stranded vectors quite well.. */

        h=(h<<4)+ch;
        if((g=h&0xf0000000))
                {
                h=h^(g>>24);
                h=h^g;
                }   
        }

h^=h2;                                    /* combine the two hashes */
return(h%LT_SYMPRIME);
}


static struct lt_symbol *lt_symadd(struct lt_trace *lt, const char *name, int hv)
{
struct lt_symbol *s;

s=(struct lt_symbol *)calloc(1,sizeof(struct lt_symbol));
strcpy(s->name=(char *)malloc((s->namlen=strlen(name))+1),name);
s->next=lt->sym[hv];
lt->sym[hv]=s;
return(s);
}


static struct lt_symbol *lt_symfind(struct lt_trace *lt, const char *s)
{
int hv;
struct lt_symbol *temp;

hv=lt_hash(s);
if(!(temp=lt->sym[hv])) return(NULL); /* no hash entry, add here wanted to add */
      
while(temp)
        {
        if(!strcmp(temp->name,s))
                {
                return(temp); /* in table already */    
                }
        if(!temp->next) break;
        temp=temp->next;
        }
      
return(NULL); /* not found, add here if you want to add*/
}


/*
 * compress facs to a prefix count + string + 0x00
 */
static void lt_compress_fac(struct lt_trace *lt, char *str)
{
int i;
int len = strlen(str);
int minlen = (len<lt->compress_fac_len) ? len : lt->compress_fac_len;

if(minlen>65535) minlen=65535;    /* keep in printable range--most hierarchies won't be this big anyway */

if(lt->compress_fac_str)
        {
        for(i=0;i<minlen;i++)
                {
                if(lt->compress_fac_str[i]!=str[i]) break;
                }
      lt_emit_u16z(lt, i);
      lt_emit_stringz(lt, str+i);
        free(lt->compress_fac_str);
        } 
        else
        {
      lt_emit_u16z(lt, 0);
      lt_emit_stringz(lt, str);
        }
         
lt->compress_fac_str = (char *) malloc((lt->compress_fac_len=len)+1);
strcpy(lt->compress_fac_str, str);
}


static void strip_brack(struct lt_symbol *s)
{
char *lastch = s->name+s->namlen - 1;
if(*lastch!=']') return;
if(s->namlen<3) return;
lastch--;
while(lastch!=s->name)
      {
      if(*lastch=='.')
            {
            return;     /* MTI SV [0.3] notation for implicit vars */
            }

      if(*lastch=='[')
            {
            *lastch=0x00;     
            return;
            }
      lastch--;   
      }
return;
}


static void lt_emitfacs(struct lt_trace *lt)
{
int i;

if((lt)&&(lt->numfacs))
      {
      struct lt_symbol *s = lt->symchain;
      char is_interlaced_trace = (lt->sorted_facs==NULL);

      if(!lt->sorted_facs)
            {
            if((lt->sorted_facs = (struct lt_symbol **)calloc(lt->numfacs, sizeof(struct lt_symbol *))))
                  {
                  if(lt->do_strip_brackets)
                  for(i=0;i<lt->numfacs;i++)
                        {
                        lt->sorted_facs[lt->numfacs - i - 1] = s; /* facs were chained backwards so reverse to restore bitslicing */
                        strip_brack(s);
                        s=s->symchain;
                        }
                  else  
                  for(i=0;i<lt->numfacs;i++)
                        {
                        lt->sorted_facs[lt->numfacs - i - 1] = s; /* facs were chained backwards so reverse to restore bitslicing*/
                        s=s->symchain;
                        }     
                  wave_msort(lt->sorted_facs, lt->numfacs);

                  for(i=0;i<lt->numfacs;i++)
                        {
                        lt->sorted_facs[i]->facnum = i;
                        }
                  }
            }

      if(lt->sorted_facs)
            {
            lt->facname_offset=lt->position;

            lt_emit_u32(lt, lt->numfacs);       /* uncompressed */
            lt_emit_u32(lt, lt->numfacbytes);   /* uncompressed */
            fflush(lt->handle);
            lt->zfacname_size = lt->position;
            lt->zhandle = gzdopen(dup(fileno(lt->handle)), "wb9");

            lt->zpackcount = 0;
            for(i=0;i<lt->numfacs;i++)
                  {
                  lt_compress_fac(lt, lt->sorted_facs[i]->name);
                  }
            free(lt->compress_fac_str); lt->compress_fac_str=NULL;
            lt->compress_fac_len=0;
            lt->zfacname_predec_size = lt->zpackcount;
      
            gzclose(lt->zhandle);
            fseeko(lt->handle, 0L, SEEK_END);
            lt->position=ftello(lt->handle);
            lt->zfacname_size = lt->position - lt->zfacname_size;

            lt->zhandle = gzdopen(dup(fileno(lt->handle)), "wb9");

            lt->facgeometry_offset = lt->position;
            for(i=0;i<lt->numfacs;i++)
                  {
                  if((lt->sorted_facs[i]->flags&LT_SYM_F_ALIAS)==0)
                        {
                        lt_emit_u32z(lt, lt->sorted_facs[i]->rows);
                        lt_emit_u32z(lt, lt->sorted_facs[i]->msb);
                        lt_emit_u32z(lt, lt->sorted_facs[i]->lsb);
                        lt_emit_u32z(lt, lt->sorted_facs[i]->flags);
                        }
                        else
                        {
                        lt_emit_u32z(lt, lt->sorted_facs[i]->aliased_to->facnum);
                        lt_emit_u32z(lt, lt->sorted_facs[i]->msb);
                        lt_emit_u32z(lt, lt->sorted_facs[i]->lsb);
                        lt_emit_u32z(lt, LT_SYM_F_ALIAS);
                        }
                  }

            gzclose(lt->zhandle);
            fseeko(lt->handle, 0L, SEEK_END);
            lt->position=ftello(lt->handle);
            lt->zfacgeometry_size = lt->position - lt->facgeometry_offset;

            if(is_interlaced_trace)
                  {
                  lt->zhandle = gzdopen(dup(fileno(lt->handle)), "wb9");
      
                  lt->sync_table_offset = lt->position;
                  for(i=0;i<lt->numfacs;i++)
                        {
                        lt_emit_u32z(lt, lt->sorted_facs[i]->last_change);
                        }
      
                  gzclose(lt->zhandle); lt->zhandle = NULL;
                  fseeko(lt->handle, 0L, SEEK_END);
                  lt->position=ftello(lt->handle);
                  lt->zsync_table_size = lt->position - lt->sync_table_offset;
                  }
            }
      }
}


/* 
 * initialize the trace and get back an lt context
 */
struct lt_trace *lt_init(const char *name)
{
struct lt_trace *lt=(struct lt_trace *)calloc(1, sizeof(struct lt_trace));

if(!(lt->handle=fopen(name, "wb")))
      {
      free(lt);
      lt=NULL;
      }
      else
      {
      lt_emit_u16(lt, LT_HDRID);
      lt_emit_u16(lt, LT_VERSION);
      lt->change_field_offset = lt->position;
      lt->initial_value = -1;                   /* if a user sets this it will have a different POSITIVE val */
      lt->timescale = -256;                     /* will be in range of -128<=x<=127 if set */

      lt_set_zmode(lt, LT_ZMODE_NONE);

      lt->mintime=ULLDescriptor(1);
      lt->maxtime=ULLDescriptor(0);
      }

return(lt);
}

/*
 * clock flushing..
 */
static void lt_flushclock(struct lt_trace *lt, struct lt_symbol *s)
{
unsigned int last_change_delta = lt->position - s->last_change - 2;
unsigned int start_position = lt->position;
int tag;
int numbytes, numbytes_trans;
int numtrans = s->clk_numtrans - LT_CLKPACK - 1;

if(numtrans<0)
      {
      /* it never got around to caching */
      fprintf(stderr, "Possible Problem with %s with %d?\n", s->name, s->clk_numtrans);
      return;
      }

if(numtrans >= 256*65536)
      {
      numbytes_trans = 3;
      }
else
if(numtrans >= 65536)
      {
      numbytes_trans = 2;
      }
else
if(numtrans >= 256)
      {
      numbytes_trans = 1;
      }
else
      {
      numbytes_trans = 0;
      }

if(!lt->numfacs_bytes)
      {
      if(last_change_delta >= 256*65536)
            {
            numbytes = 3;
            }
      else
      if(last_change_delta >= 65536)
            {
            numbytes = 2;
            }
      else
      if(last_change_delta >= 256)
            {
            numbytes = 1;
            }
      else
            {
            numbytes = 0;
            }

      tag = (numbytes<<4) + 0xC + numbytes_trans;     /* yields xC..xF */

      lt->lt_emit_u8(lt, tag);
      switch(numbytes&3)
            {
            case 0: lt->lt_emit_u8(lt, last_change_delta); break;
            case 1: lt->lt_emit_u16(lt, last_change_delta); break;
            case 2: lt->lt_emit_u24(lt, last_change_delta); break;
            case 3: lt->lt_emit_u32(lt, last_change_delta); break;
            }
      }
      else
      {
      tag = 0xC + numbytes_trans;   /* yields C..F */

      switch(lt->numfacs_bytes)
            {
            case 1: lt->lt_emit_u8(lt, s->facnum); break;
            case 2: lt->lt_emit_u16(lt, s->facnum); break;
            case 3: lt->lt_emit_u24(lt, s->facnum); break;
            case 4: lt->lt_emit_u32(lt, s->facnum); break;
            }
      lt->lt_emit_u8(lt, tag);
      }

s->last_change = start_position;

/* s->clk_prevval       CAN BE INFERRED! */
/* s->clk_prevtrans           CAN BE INFERRED! */
/* s->clk_delta         CAN BE INFERRED! */

switch(numbytes_trans&3)
      {
      case 0: lt->lt_emit_u8(lt, numtrans); break;
      case 1: lt->lt_emit_u16(lt, numtrans); break;
      case 2: lt->lt_emit_u24(lt, numtrans); break;
      case 3: lt->lt_emit_u32(lt, numtrans); break;
      }

/* printf("Clock finish for '%s' at %lld ending with '%c' for %d repeats over a switch delta of %d\n", 
      s->name, lt->timeval, s->clk_prevval, s->clk_numtrans - LT_CLKPACK, s->clk_delta); */
s->clk_prevtrans = ULLDescriptor(~0);
s->clk_numtrans = 0;
}

static void lt_flushclock_m(struct lt_trace *lt, struct lt_symbol *s)
{
unsigned int last_change_delta = lt->position - s->last_change - 2;
unsigned int start_position = lt->position;
int tag;
int numbytes, numbytes_trans;
int numtrans = s->clk_numtrans - LT_CLKPACK_M - 1;

if(numtrans<0)
      {
      /* it never got around to caching */
      fprintf(stderr, "Possible Problem with %s with %d?\n", s->name, s->clk_numtrans);
      return;
      }

if(numtrans >= 256*65536)
      {
      numbytes_trans = 3;
      }
else
if(numtrans >= 65536)
      {
      numbytes_trans = 2;
      }
else
if(numtrans >= 256)
      {
      numbytes_trans = 1;
      }
else
      {
      numbytes_trans = 0;
      }

if(!lt->numfacs_bytes)
      {
      if(last_change_delta >= 256*65536)
            {
            numbytes = 3;
            }
      else
      if(last_change_delta >= 65536)
            {
            numbytes = 2;
            }
      else
      if(last_change_delta >= 256)
            {
            numbytes = 1;
            }
      else
      {
      numbytes = 0;
      }

      tag = (numbytes<<4) + 0xC + numbytes_trans;     /* yields xC..xF */

      lt->lt_emit_u8(lt, tag);
      switch(numbytes&3)
            {
            case 0: lt->lt_emit_u8(lt, last_change_delta); break;
            case 1: lt->lt_emit_u16(lt, last_change_delta); break;
            case 2: lt->lt_emit_u24(lt, last_change_delta); break;
            case 3: lt->lt_emit_u32(lt, last_change_delta); break;
            }
      }
      else
      {
      tag = 0xC + numbytes_trans;   /* yields C..F */

      switch(lt->numfacs_bytes)
            {
            case 1: lt->lt_emit_u8(lt, s->facnum); break;
            case 2: lt->lt_emit_u16(lt, s->facnum); break;
            case 3: lt->lt_emit_u24(lt, s->facnum); break;
            case 4: lt->lt_emit_u32(lt, s->facnum); break;
            }
      lt->lt_emit_u8(lt, tag);
      }


s->last_change = start_position;

/* s->clk_prevval       CAN BE INFERRED! */
/* s->clk_prevtrans           CAN BE INFERRED! */
/* s->clk_delta         CAN BE INFERRED! */

switch(numbytes_trans&3)
      {
      case 0: lt->lt_emit_u8(lt, numtrans); break;
      case 1: lt->lt_emit_u16(lt, numtrans); break;
      case 2: lt->lt_emit_u24(lt, numtrans); break;
      case 3: lt->lt_emit_u32(lt, numtrans); break;
      }

/* printf("Clock finish for '%s' at %lld ending with '%08x' for %d repeats over a switch delta of %lld\n", 
      s->name, lt->timeval, s->clk_prevval, s->clk_numtrans - LT_CLKPACK_M, s->clk_delta); */
s->clk_prevtrans = ULLDescriptor(~0);
s->clk_numtrans = 0;
}


/*
 * recurse through dictionary
 */
static void lt_recurse_dictionary(struct lt_trace *lt, dslxt_Tree *ds)
{
if(ds->left) lt_recurse_dictionary(lt, ds->left);
lt->sorted_dict[ds->val] = ds;
if(ds->right) lt_recurse_dictionary(lt, ds->right);
}

static void lt_recurse_dictionary_free(struct lt_trace *lt, dslxt_Tree *ds)
{
dslxt_Tree *lft = ds->left;
dslxt_Tree *rgh = ds->right;

if(lft) lt_recurse_dictionary_free(lt, lft);
free(ds->item); free(ds);
if(rgh) lt_recurse_dictionary_free(lt, rgh);
}

static int lt_dictval_compare(const void *v1, const void *v2)
{
dslxt_Tree *s1 = *(dslxt_Tree **)v1;
dslxt_Tree *s2 = *(dslxt_Tree **)v2;

if(s1->val > s2->val) return(1); else return(-1);     /* they're *never* equal */
}

static void lt_finalize_dictionary(struct lt_trace *lt)
{
int i;

lt->sorted_dict = calloc(lt->num_dict_entries, sizeof(dslxt_Tree *));

lt->dictionary_offset=lt->position;

lt_emit_u32(lt, lt->num_dict_entries);          /* uncompressed */
lt_emit_u32(lt, lt->dict_string_mem_required - lt->num_dict_entries);   /* uncompressed : minus because leading '1' is implied so its stripped */
lt_emit_u32(lt, lt->dict16_offset);       /* uncompressed */
lt_emit_u32(lt, lt->dict24_offset);       /* uncompressed */
lt_emit_u32(lt, lt->dict32_offset);       /* uncompressed */
lt_emit_u32(lt, lt->mindictwidth);        /* uncompressed */
fflush(lt->handle);

#if 0
fprintf(stderr, "*** dictionary_offset = %08x\n", lt->dictionary_offset);
fprintf(stderr, "*** num_dict_entries = %d\n", lt->num_dict_entries);
#endif

lt->zdictionary_size = lt->position;
lt->zhandle = gzdopen(dup(fileno(lt->handle)), "wb9");

lt_recurse_dictionary(lt, lt->dict);
qsort((void *)lt->sorted_dict, lt->num_dict_entries, sizeof(struct dsTree **), lt_dictval_compare);

for(i=0;i<lt->num_dict_entries;i++)
      {
      dslxt_Tree *ds = lt->sorted_dict[i];
      /* fprintf(stderr, "%8d) '%s'\n", ds->val, ds->item); */
      lt_emit_stringz(lt, ds->item+1);
      }
      
gzclose(lt->zhandle);
fseeko(lt->handle, 0L, SEEK_END);
lt->position=ftello(lt->handle);
lt->zdictionary_size = lt->position - lt->zdictionary_size;

free(lt->sorted_dict); lt->sorted_dict = NULL;

lt_recurse_dictionary_free(lt, lt->dict);
lt->dict = NULL;
}


/*
 * close out the trace and fixate it
 */
void lt_close(struct lt_trace *lt)
{
lxttime_t lasttime=ULLDescriptor(0);
int lastposition=0;
char is64=0;

if(lt)
      {
      struct lt_symbol *s = lt->symchain;

      if(lt->clock_compress)
      while(s)
            {
               if(s->clk_prevtrans!=ULLDescriptor(~0))
                        {
                        int len = ((s->flags)&LT_SYM_F_INTEGER) ? 32 : s->len;
                        if(len>1)
                                {
                                if(s->clk_numtrans > LT_CLKPACK_M) lt_flushclock_m(lt, s);
                                }
                                else
                                {   
                                if(s->clk_numtrans > LT_CLKPACK) lt_flushclock(lt, s);
                                }
                        }
                         
                s=s->symchain;
            }     

      lt_set_dumpon(lt);      /* in case it was turned off */

      if(lt->zmode!=LT_ZMODE_NONE)
            {
            lt->chg_table_size = lt->position - lt->change_field_offset;

            switch(lt->zmode)
                  {
                  case LT_ZMODE_GZIP:     gzclose(lt->zhandle); break;
                  case LT_ZMODE_BZIP2:    BZ2_bzclose(lt->zhandle); break;
                  }
            lt->zhandle = NULL;
            fseeko(lt->handle, 0L, SEEK_END);
            lt->position=ftello(lt->handle);

            lt_set_zmode(lt, LT_ZMODE_NONE);
            lt->zchg_table_size = lt->position - lt->change_field_offset;
            }

      lt_emitfacs(lt);
      if(lt->dict) lt_finalize_dictionary(lt);

      if(lt->timebuff)
            {
            free(lt->timebuff);
            lt->timebuff=NULL;
            }
      if(lt->timehead)
            {
            struct lt_timetrail *t=lt->timehead;
            struct lt_timetrail *t2;

            lt->time_table_offset = lt->position;

            lt_emit_u32(lt, lt->timechangecount);     /* this is uncompressed! */

            fflush(lt->handle);
            lt->zhandle = gzdopen(dup(fileno(lt->handle)), "wb9");
            lt->ztime_table_size = lt->position;

            is64=(lt->maxtime > ULLDescriptor(0xFFFFFFFF));

            if(is64)
                  {
                  lt_emit_u64z(lt, (int)((lt->mintime)>>32), (int)lt->mintime);
                  lt_emit_u64z(lt, (int)((lt->maxtime)>>32), (int)lt->maxtime);
                  }
                  else
                  {
                  lt_emit_u32z(lt, (int)lt->mintime);
                  lt_emit_u32z(lt, (int)lt->maxtime);
                  }

            while(t)
                  {
                  lt_emit_u32z(lt, t->position - lastposition); lastposition = t->position;
                  t=t->next;              
                  }

            t=lt->timehead;
            if(is64)
                  {
                  while(t)
                        {
                        lxttime_t delta = t->timeval - lasttime;
                        lt_emit_u64z(lt, (int)(delta>>32), (int)delta); lasttime = t->timeval;
                        
                        t2=t->next;
                        free(t);                
                        t=t2;
                        }
                  }
            else
                  {
                  while(t)
                        {
                        lt_emit_u32z(lt, (int)(t->timeval - lasttime)); lasttime = t->timeval;
                        
                        t2=t->next;
                        free(t);                
                        t=t2;
                        }
      
                  lt->timehead = lt->timecurr = NULL;
                  }

            gzclose(lt->zhandle); lt->zhandle = NULL;
            fseeko(lt->handle, 0L, SEEK_END);
            lt->position=ftello(lt->handle);
            lt->ztime_table_size = lt->position - lt->ztime_table_size;
            }

      if(lt->initial_value>=0) 
            {
            lt->initial_value_offset = lt->position;
            lt_emit_u8(lt, lt->initial_value);
            }

      if((lt->timescale>-129)&(lt->timescale<128))
            {
            lt->timescale_offset = lt->position;
            lt_emit_u8(lt, lt->timescale);
            }

      if(lt->double_used)
            {
            lt->double_test_offset = lt->position;
            lt_emit_double(lt, 3.14159);        
            }

      if(lt->dumpoffcount)
            {
            struct lt_timetrail *ltt = lt->dumpoffhead;
            struct lt_timetrail *ltt2;

            lt->exclude_offset = lt->position;
            lt_emit_u32(lt, lt->dumpoffcount);

            while(ltt)
                  {
                  lt_emit_u64(lt, (int)((ltt->timeval)>>32), (int)ltt->timeval);
                  ltt2 = ltt;
                  ltt=ltt->next;
                  free(ltt2);             
                  }

            lt->dumpoffhead = lt->dumpoffcurr = NULL;
            lt->dumpoffcount = 0;
            }

      /* prefix */
      lt_emit_u8(lt, LT_SECTION_END);

      /* Version 1 */
      if(lt->change_field_offset) { lt_emit_u32(lt, lt->change_field_offset); lt_emit_u8(lt, LT_SECTION_CHG); }
      if(lt->sync_table_offset) { lt_emit_u32(lt, lt->sync_table_offset); lt_emit_u8(lt, LT_SECTION_SYNC_TABLE); }
      if(lt->facname_offset) { lt_emit_u32(lt, lt->facname_offset); lt_emit_u8(lt, LT_SECTION_FACNAME); }
      if(lt->facgeometry_offset) { lt_emit_u32(lt, lt->facgeometry_offset); lt_emit_u8(lt, LT_SECTION_FACNAME_GEOMETRY); }
      if(lt->timescale_offset) { lt_emit_u32(lt, lt->timescale_offset); lt_emit_u8(lt, LT_SECTION_TIMESCALE); }
      if(lt->time_table_offset) { lt_emit_u32(lt, lt->time_table_offset); lt_emit_u8(lt, is64 ? LT_SECTION_TIME_TABLE64 : LT_SECTION_TIME_TABLE); }
      if(lt->initial_value_offset) { lt_emit_u32(lt, lt->initial_value_offset); lt_emit_u8(lt, LT_SECTION_INITIAL_VALUE); }
      if(lt->double_test_offset) { lt_emit_u32(lt, lt->double_test_offset); lt_emit_u8(lt, LT_SECTION_DOUBLE_TEST); }

      /* Version 2 adds */
      if(lt->zfacname_predec_size) { lt_emit_u32(lt, lt->zfacname_predec_size); lt_emit_u8(lt, LT_SECTION_ZFACNAME_PREDEC_SIZE); }
      if(lt->zfacname_size) { lt_emit_u32(lt, lt->zfacname_size); lt_emit_u8(lt, LT_SECTION_ZFACNAME_SIZE); }
      if(lt->zfacgeometry_size) { lt_emit_u32(lt, lt->zfacgeometry_size); lt_emit_u8(lt, LT_SECTION_ZFACNAME_GEOMETRY_SIZE); }
      if(lt->zsync_table_size) { lt_emit_u32(lt, lt->zsync_table_size); lt_emit_u8(lt, LT_SECTION_ZSYNC_SIZE); }
      if(lt->ztime_table_size) { lt_emit_u32(lt, lt->ztime_table_size); lt_emit_u8(lt, LT_SECTION_ZTIME_TABLE_SIZE); }
      if(lt->chg_table_size) { lt_emit_u32(lt, lt->chg_table_size); lt_emit_u8(lt, LT_SECTION_ZCHG_PREDEC_SIZE); }
      if(lt->zchg_table_size) { lt_emit_u32(lt, lt->zchg_table_size); lt_emit_u8(lt, LT_SECTION_ZCHG_SIZE); }

      /* Version 4 adds */
      if(lt->dictionary_offset) { lt_emit_u32(lt, lt->dictionary_offset); lt_emit_u8(lt, LT_SECTION_ZDICTIONARY); }
      if(lt->zdictionary_size) { lt_emit_u32(lt, lt->zdictionary_size); lt_emit_u8(lt, LT_SECTION_ZDICTIONARY_SIZE); }

      /* Version 5 adds */
      if(lt->exclude_offset) { lt_emit_u32(lt, lt->exclude_offset); lt_emit_u8(lt, LT_SECTION_EXCLUDE_TABLE); }

      /* suffix */
      lt_emit_u8(lt, LT_TRLID);

      if(lt->symchain)
            {
            struct lt_symbol *s = lt->symchain;
            struct lt_symbol *s2;
            
            while(s)
                  {
                  free(s->name);
                  s2=s->symchain;
                  free(s);
                  s=s2;
                  }
            }
      
      free(lt->sorted_facs);
      fclose(lt->handle);
      free(lt);
      }

}


/*
 * maint function for finding a symbol if it exists
 */
struct lt_symbol *lt_symbol_find(struct lt_trace *lt, const char *name)
{
struct lt_symbol *s=NULL;

if((lt)&&(name)) s=lt_symfind(lt, name);
return(s);
}


/*
 * add a trace (if it doesn't exist already)
 */
struct lt_symbol *lt_symbol_add(struct lt_trace *lt, const char *name, unsigned int rows, int msb, int lsb, int flags)
{
struct lt_symbol *s;
int len;
int flagcnt;

if((!lt)||(lt->sorted_facs)) return(NULL);

flagcnt = ((flags&LT_SYM_F_INTEGER)!=0) + ((flags&LT_SYM_F_DOUBLE)!=0) + ((flags&LT_SYM_F_STRING)!=0);

if((flagcnt>1)||(!lt)||(!name)||(lt_symfind(lt, name))) return (NULL);

if(flags&LT_SYM_F_DOUBLE) lt->double_used = 1;

s=lt_symadd(lt, name, lt_hash(name));
s->rows = rows;
s->flags = flags&(~LT_SYM_F_ALIAS); /* aliasing makes no sense here.. */

if(!flagcnt)
      {
      s->msb = msb;
      s->lsb = lsb;
      s->len = (msb<lsb) ? (lsb-msb+1) : (msb-lsb+1);

      if((s->len==1)&&(s->rows==0)) s->clk_prevtrans = ULLDescriptor(~0);
      }

s->symchain = lt->symchain;
lt->symchain = s;

lt->numfacs++;

if((len=strlen(name)) > lt->longestname) lt->longestname = len;
lt->numfacbytes += (len+1);

return(s);
}

/*
 * add an alias trace (if it doesn't exist already and orig is found)
 */
struct lt_symbol *lt_symbol_alias(struct lt_trace *lt, const char *existing_name, const char *alias, int msb, int lsb)
{
struct lt_symbol *s, *sa;
int len;
int bitlen;
int flagcnt;

if((!lt)||(!existing_name)||(!alias)||(!(s=lt_symfind(lt, existing_name)))||(lt_symfind(lt, alias))) return (NULL);

if(lt->sorted_facs) return(NULL);

while(s->aliased_to)    /* find root alias */
      {
      s=s->aliased_to;
      }

flagcnt = ((s->flags&LT_SYM_F_INTEGER)!=0) + ((s->flags&LT_SYM_F_DOUBLE)!=0) + ((s->flags&LT_SYM_F_STRING)!=0);
bitlen = (msb<lsb) ? (lsb-msb+1) : (msb-lsb+1);
if((!flagcnt)&&(bitlen!=s->len)) return(NULL);

sa=lt_symadd(lt, alias, lt_hash(alias));
sa->flags = LT_SYM_F_ALIAS;   /* only point this can get set */
sa->aliased_to = s;

if(!flagcnt)
      {
      sa->msb = msb;
      sa->lsb = lsb;
      sa->len = bitlen;
      }

sa->symchain = lt->symchain;
lt->symchain = sa;
lt->numfacs++;
if((len=strlen(alias)) > lt->longestname) lt->longestname = len;
lt->numfacbytes += (len+1);

return(sa);
}


/* 
 * set current time
 */
int lt_inc_time_by_delta(struct lt_trace *lt, unsigned int timeval)
{
return(lt_set_time64(lt, lt->maxtime + (lxttime_t)timeval));
}

int lt_set_time(struct lt_trace *lt, unsigned int timeval)
{
return(lt_set_time64(lt, (lxttime_t)timeval));
}

int lt_inc_time_by_delta64(struct lt_trace *lt, lxttime_t timeval)
{
return(lt_set_time64(lt, lt->maxtime + timeval));
}

int lt_set_time64(struct lt_trace *lt, lxttime_t timeval)
{
int rc=0;

if(lt)
      {
      struct lt_timetrail *trl=(struct lt_timetrail *)calloc(1, sizeof(struct lt_timetrail));
      if(trl)
            {
            trl->timeval = timeval;
            trl->position = lt->position;

            if((lt->timecurr)||(lt->timebuff))
                  {
                  if(((timeval>lt->mintime)&&(timeval>lt->maxtime))||((lt->mintime==ULLDescriptor(1))&&(lt->maxtime==ULLDescriptor(0))))
                        {
                        lt->maxtime = timeval;
                        }
                        else
                        {
                        free(trl);
                        goto bail;                    
                        }
                  }
                  else
                  {
                  lt->mintime = lt->maxtime = timeval;
                  }

            if(lt->timebuff)
                  {
                  free(lt->timebuff);
                  }
            lt->timebuff = trl;
            lt->timeval = timeval;
            rc=1;
            }
      }

bail:
return(rc);
}


/*
 * sets trace timescale as 10**x seconds
 */
void lt_set_timescale(struct lt_trace *lt, int timescale)
{
if(lt)
      {
      lt->timescale = timescale;
      }
}


/*
 * sets clock compression heuristic
 */
void lt_set_clock_compress(struct lt_trace *lt)
{
if(lt)
      {
      lt->clock_compress = 1;
      }
}


/*
 * sets change dump compression
 */
void lt_set_chg_compress(struct lt_trace *lt)
{
if(lt)
      {
      if((lt->zmode==LT_ZMODE_NONE)&&(!lt->emitted))
            {
            lt_set_zmode(lt, lt->zmode = LT_ZMODE_GZIP);
            fflush(lt->handle);
            lt->zhandle = gzdopen(dup(fileno(lt->handle)), "wb9");
            }
      }
}


/*
 * sets change dictionary compression
 */
void lt_set_dict_compress(struct lt_trace *lt, unsigned int minwidth)
{
if((lt)&&(!lt->emitted))
      {
      lt->dictmode = 1;

      if(minwidth>1)
            {
            lt->mindictwidth = minwidth;
            }
      }
}

/*
 * sets change interlace 
 */
void lt_set_no_interlace(struct lt_trace *lt)
{
if((lt)&&(!lt->emitted)&&(!lt->sorted_facs))
      {
      if(lt->zmode==LT_ZMODE_NONE)        /* this mode implies BZIP2 compression! */
            {
            lt_set_zmode(lt, lt->zmode = LT_ZMODE_BZIP2);
            fflush(lt->handle);
            lt->zhandle = BZ2_bzdopen(dup(fileno(lt->handle)), "wb9");
            }

      if((lt->sorted_facs = (struct lt_symbol **)calloc(lt->numfacs, sizeof(struct lt_symbol *))))
            {
            struct lt_symbol *s = lt->symchain;
            int i;

            if(lt->do_strip_brackets)
            for(i=0;i<lt->numfacs;i++)
                  {
                  lt->sorted_facs[lt->numfacs - i - 1] = s; /* facs were chained backwards so reverse to restore bitslicing */
                  strip_brack(s);
                  s=s->symchain;
                  }
            else  
            for(i=0;i<lt->numfacs;i++)
                  {
                  lt->sorted_facs[lt->numfacs - i - 1] = s; /* facs were chained backwards so reverse to restore bitslicing */
                  s=s->symchain;
                  }     
            wave_msort(lt->sorted_facs, lt->numfacs);

            for(i=0;i<lt->numfacs;i++)
                  {
                  lt->sorted_facs[i]->facnum = i;
                  }

            if(lt->numfacs >= 256*65536)
                  {
                  lt->numfacs_bytes = 4;
                  }
            else
            if(lt->numfacs >= 65536)
                  {
                  lt->numfacs_bytes = 3;
                  }
            else
            if(lt->numfacs >= 256)
                  {
                  lt->numfacs_bytes = 2;
                  }
            else
                  {
                  lt->numfacs_bytes = 1;
                  }
            }
      }
}


/*
 * sets trace initial value
 */
void lt_set_initial_value(struct lt_trace *lt, char value)
{
if(lt)
      {
      int tag;
      switch(value)
            {           
            case '0':   tag = 0; break;
            case '1':   tag = 1; break;
            case 'Z':   
            case 'z':   tag = 2; break;
            case 'X':   
            case 'x':   tag = 3; break;
            case 'H':
            case 'h':   tag = 4; break;
            case 'U':
            case 'u':   tag = 5; break;
            case 'W':
            case 'w':   tag = 6; break;
            case 'L':
            case 'l':   tag = 0x7; break;
            case '-':   tag = 0x8; break;
            default:    tag = -1;  break;
            }
      lt->initial_value = tag;
      }
}


/*
 * Sets bracket stripping (useful for VCD conversions of
 * bitblasted nets)
 */
void lt_symbol_bracket_stripping(struct lt_trace *lt, int doit)
{
if(lt)
      {
      lt->do_strip_brackets = (doit!=0);
      }
}


/*
 * emission for trace values..
 */
static int lt_optimask[]=
{
0x00000000,

0x00000001,
0x00000003,
0x00000007,
0x0000000f,

0x0000001f,
0x0000003f,
0x0000007f,
0x000000ff,

0x000001ff,
0x000003ff,
0x000007ff,
0x00000fff,

0x00001fff,
0x00003fff,
0x00007fff,
0x0000ffff,

0x0001ffff,
0x0003ffff,
0x0007ffff,
0x000fffff,

0x001fffff,
0x003fffff,
0x007fffff,
0x00ffffff,

0x01ffffff,
0x03ffffff,
0x07ffffff,
0x0fffffff,

0x1fffffff,
0x3fffffff,
0x7fffffff,
0xffffffff
};


static char *lt_expand_integer_to_bits(int len, int value)
{
static char s[33];
char *p = s;
int i;

len--;

for(i=0;i<=len;i++)
      {
      *(p++) = '0' | ((value & (1<<(len-i)))!=0);
      }
*p = 0;

return(s);
}


int lt_emit_value_int(struct lt_trace *lt, struct lt_symbol *s, unsigned int row, int value)
{
int rc=0;

if((!lt)||(!s)) return(rc);

if(!lt->emitted) lt->emitted = 1;

while(s->aliased_to)    /* find root alias if exists */
      {
      s=s->aliased_to;
      }

if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING)))
      {
      int numbytes;                       /* number of bytes to store value minus one */
      int len = ((s->flags)&LT_SYM_F_INTEGER) ? 32 : s->len;
      unsigned int last_change_delta;

      if((lt->clock_compress)&&(s->rows==0))
      {
      if((len>1)&&(len<=32))
            {
            int ivalue = value;
            int delta1, delta2;
            s->clk_mask <<= 1;
            s->clk_mask |= 1;

            if(     ((s->clk_mask&0x1f)==0x1f) && 
                  ( (delta1=(ivalue         - s->clk_prevval1) & lt_optimask[s->len]) == ((s->clk_prevval1 - s->clk_prevval3) & lt_optimask[s->len]) ) &&
                  ( (delta2=(s->clk_prevval - s->clk_prevval2) & lt_optimask[s->len]) == ((s->clk_prevval2 - s->clk_prevval4) & lt_optimask[s->len]) ) &&
                  ( (delta1==delta2) || ((!delta1)&&(!delta2)) )
                  )
                  {
                  if(s->clk_prevtrans==ULLDescriptor(~0))
                        {
                        s->clk_prevtrans = lt->timeval;
                        s->clk_numtrans = 0;
                        }
                  else
                  if(s->clk_numtrans == 0)
                        {
                        s->clk_delta = lt->timeval - s->clk_prevtrans;
                        s->clk_prevtrans = lt->timeval;
                        s->clk_numtrans++;
                        }
                  else
                        {
                        if(s->clk_delta == (lt->timeval - s->clk_prevtrans))
                              {
                              s->clk_numtrans++;
                              s->clk_prevtrans = lt->timeval;
                              if(s->clk_numtrans > LT_CLKPACK_M)
                                    {
                                    s->clk_prevval4 = s->clk_prevval3;
                                    s->clk_prevval3 = s->clk_prevval2;
                                    s->clk_prevval2 = s->clk_prevval1;
                                    s->clk_prevval1 = s->clk_prevval;
                                    s->clk_prevval  = ivalue;

                                    /* printf("Clock value '%08x' for '%s' at %lld (#%d)\n", ivalue, s->name, lt->timeval, s->clk_numtrans); */
                                    return(1);
                                    }
                              }
                              else
                              {
                              if(s->clk_numtrans > LT_CLKPACK_M)
                                    {
                                    lt_flushclock_m(lt, s);
                                    /* flush clock then continue below! */
                                    }
                                    else
                                    {
                                    s->clk_prevtrans=ULLDescriptor(~0);
                                    }
                              }
                        }

                  }
                  else
                  {
                  if(s->clk_numtrans > LT_CLKPACK_M)
                        {
                        lt_flushclock_m(lt, s);
                        /* flush clock then continue below! */
                        }
                        else
                        {
                        s->clk_prevtrans=ULLDescriptor(~0);
                        }
                  }

            s->clk_prevval4 = s->clk_prevval3;
            s->clk_prevval3 = s->clk_prevval2;
            s->clk_prevval2 = s->clk_prevval1;
            s->clk_prevval1 = s->clk_prevval;
            s->clk_prevval  = ivalue;
            }
      else
      if(len==1) /* possible clock handling */
            {
            int ivalue = value&1;

            if(((s->clk_prevval == '1') && (ivalue==0)) || ((s->clk_prevval == '0') && (ivalue==1)))
                  {
                  if(s->clk_prevtrans==ULLDescriptor(~0))
                        {
                        s->clk_prevtrans = lt->timeval;
                        s->clk_numtrans = 0;
                        }
                  else
                  if(s->clk_numtrans == 0)
                        {
                        s->clk_delta = lt->timeval - s->clk_prevtrans;
                        s->clk_prevtrans = lt->timeval;
                        s->clk_numtrans++;
                        }
                  else
                        {
                        if(s->clk_delta == (lt->timeval - s->clk_prevtrans))
                              {
                              s->clk_numtrans++;
                              s->clk_prevtrans = lt->timeval;
                              if(s->clk_numtrans > LT_CLKPACK)
                                    {
                                    s->clk_prevval = ivalue + '0';

                                    /* printf("Clock value '%d' for '%s' at %d (#%d)\n", ivalue, s->name, lt->timeval, s->clk_numtrans); */
                                    return(1);
                                    }
                              }
                              else
                              {
                              if(s->clk_numtrans > LT_CLKPACK)
                                    {
                                    lt_flushclock(lt, s);
                                    /* flush clock then continue below! */
                                    }
                                    else
                                    {
                                    s->clk_prevtrans=ULLDescriptor(~0);
                                    }
                              }
                        }

                  }
                  else
                  {
                  if(s->clk_numtrans > LT_CLKPACK)
                        {
                        lt_flushclock(lt, s);
                        /* flush clock then continue below! */
                        }
                        else
                        {
                        s->clk_prevtrans=ULLDescriptor(~0);
                        }
                  }

            s->clk_prevval = ivalue + '0';
            }
      }

      /* normal trace handling */

      last_change_delta = lt->position - s->last_change - 2;

      if(last_change_delta >= 256*65536)
            {
            numbytes = 3;
            }
      else
      if(last_change_delta >= 65536)
            {
            numbytes = 2;
            }
      else
      if(last_change_delta >= 256)
            {
            numbytes = 1;
            }
      else
            {
            numbytes = 0;
            }

      if(len<=32)
            {
            int start_position = lt->position;
            int tag;
            int optimized0 = ((value&lt_optimask[len])==0);
            int optimized1 = ((value&lt_optimask[len])==lt_optimask[len]);
            int optimized  = optimized0|optimized1;

            if(!lt->numfacs_bytes)
                  {
                  if(optimized)
                        {
                        tag = (numbytes<<4) | (3+optimized1);     /* for x3 and x4 cases */
                        }
                        else
                        {
                        tag = (numbytes<<4);
                        }
      
                  lt->lt_emit_u8(lt, tag);
                  switch(numbytes&3)
                        {
                        case 0: lt->lt_emit_u8(lt, last_change_delta); break;
                        case 1: lt->lt_emit_u16(lt, last_change_delta); break;
                        case 2: lt->lt_emit_u24(lt, last_change_delta); break;
                        case 3: lt->lt_emit_u32(lt, last_change_delta); break;
                        }
                  }
                  else
                  {
                  switch(lt->numfacs_bytes)
                        {
                        case 1: lt->lt_emit_u8(lt, s->facnum); break;
                        case 2: lt->lt_emit_u16(lt, s->facnum); break;
                        case 3: lt->lt_emit_u24(lt, s->facnum); break;
                        case 4: lt->lt_emit_u32(lt, s->facnum); break;
                        }
                  lt->lt_emit_u8(lt, optimized ? (3+optimized1) : 0);
                  }
      
            s->last_change = start_position;

            if(s->rows>0)
                  {
                  if(s->rows >= 256*65536)
                        {
                        numbytes = 3;
                        }
                  else
                  if(s->rows >= 65536)
                        {
                        numbytes = 2;
                        }
                  else
                  if(s->rows >= 256)
                        {
                        numbytes = 1;
                        }
                  else
                        {
                        numbytes = 0;
                        }

                  switch(numbytes&3)
                        {
                        case 0: lt->lt_emit_u8(lt, row); break;
                        case 1: lt->lt_emit_u16(lt, row); break;
                        case 2: lt->lt_emit_u24(lt, row); break;
                        case 3: lt->lt_emit_u32(lt, row); break;
                        }
                  }

            if(!optimized)
                  {
                  if((lt->dictmode)&&(len>lt->mindictwidth))
                        {
                        char *vpnt_orig = lt_expand_integer_to_bits(len, value);
                        char *vpnt = vpnt_orig;

                        while ( (*vpnt == '0') && (*(vpnt+1)) ) vpnt++;

                        lt->dict = dslxt_splay (vpnt, lt->dict);
                        if(!dslxt_success)
                              {
                              unsigned int vlen = strlen(vpnt)+1;
                              char *vcopy = (char *)malloc(vlen);

                              strcpy(vcopy, vpnt);
                              lt->dict_string_mem_required += vlen;
                              lt->dict = dslxt_insert(vcopy, lt->dict, lt->num_dict_entries);

                              if(!lt->dict16_offset)
                                    {
                                    if(lt->num_dict_entries==256) lt->dict16_offset = lt->position;
                                    }
                              else
                              if(!lt->dict24_offset)
                                    {
                                    if(lt->num_dict_entries==65536) lt->dict24_offset = lt->position;
                                    }
                              else
                              if(!lt->dict32_offset)
                                    {
                                    if(lt->num_dict_entries==(256*65536)) lt->dict32_offset = lt->position;
                                    }
                  
                              lt->num_dict_entries++;
                              }

                        if(lt->dict24_offset)
                              {
                              if(lt->dict32_offset)
                                    {
                                    lt->lt_emit_u32(lt, lt->dict->val);
                                    }
                                    else
                                    {
                                    lt->lt_emit_u24(lt, lt->dict->val);
                                    }
                              }
                        else
                              {
                              if(lt->dict16_offset)
                                    {
                                    lt->lt_emit_u16(lt, lt->dict->val);
                                    }
                                    else
                                    {
                                    lt->lt_emit_u8(lt, lt->dict->val);
                                    }
                              }
                        }
                  else
                  if(len<9)
                        {
                        value <<= (8-len);
                        rc=lt->lt_emit_u8(lt, value);
                        }
                  else
                  if(len<17)
                        {
                        value <<= (16-len);
                        rc=lt->lt_emit_u16(lt, value);
                        }
                  else
                  if(len<25)
                        {
                        value <<= (24-len);
                        rc=lt->lt_emit_u24(lt, value);
                        }
                  else              
                        {
                        value <<= (32-len);
                        rc=lt->lt_emit_u32(lt, value);
                        }
                  }
            }     
      
      if(lt->timebuff)
            {
            lt->timechangecount++;
            if(lt->timecurr)
                  {
                  lt->timecurr->next = lt->timebuff;
                  lt->timecurr = lt->timebuff;
                  }
                  else
                  {
                  lt->timehead = lt->timecurr = lt->timebuff;
                  }

            lt->timebuff=NULL;
            }
      }

return(rc);
}


int lt_emit_value_double(struct lt_trace *lt, struct lt_symbol *s, unsigned int row, double value)
{
int rc=0;
int start_position;
int tag;

if((!lt)||(!s)) return(rc);

if(!lt->emitted) lt->emitted = 1;

while(s->aliased_to)    /* find root alias if exists */
      {
      s=s->aliased_to;
      }

if((s->flags)&LT_SYM_F_DOUBLE)
      {
      int numbytes;                       /* number of bytes to store value minus one */
      unsigned int last_change_delta = lt->position - s->last_change - 2;

      if(!lt->numfacs_bytes)
            {
            if(last_change_delta >= 256*65536)
                  {
                  numbytes = 3;
                  }
            else
            if(last_change_delta >= 65536)
                  {
                  numbytes = 2;
                  }
            else
            if(last_change_delta >= 256)
                  {
                  numbytes = 1;
                  }
            else
                  {
                  numbytes = 0;
                  }
      
            start_position = lt->position;
            s->last_change = start_position;

            tag = (numbytes<<4);
            lt->lt_emit_u8(lt, tag);
            switch(numbytes&3)
                  {
                  case 0: lt->lt_emit_u8(lt, last_change_delta); break;
                  case 1: lt->lt_emit_u16(lt, last_change_delta); break;
                  case 2: lt->lt_emit_u24(lt, last_change_delta); break;
                  case 3: lt->lt_emit_u32(lt, last_change_delta); break;
                  }
            }
            else
            {
            switch(lt->numfacs_bytes)
                  {
                  case 1: lt->lt_emit_u8(lt, s->facnum); break;
                  case 2: lt->lt_emit_u16(lt, s->facnum); break;
                  case 3: lt->lt_emit_u24(lt, s->facnum); break;
                  case 4: lt->lt_emit_u32(lt, s->facnum); break;
                  }
            }

      if(s->rows>0)
            {
            if(s->rows >= 256*65536)
                  {
                  numbytes = 3;
                  }
            else
            if(s->rows >= 65536)
                  {
                  numbytes = 2;
                  }
            else
            if(s->rows >= 256)
                  {
                  numbytes = 1;
                  }
            else
                  {
                  numbytes = 0;
                  }

            switch(numbytes&3)
                  {
                  case 0: lt->lt_emit_u8(lt, row); break;
                  case 1: lt->lt_emit_u16(lt, row); break;
                  case 2: lt->lt_emit_u24(lt, row); break;
                  case 3: lt->lt_emit_u32(lt, row); break;
                  }
            }

      rc=lt->lt_emit_double(lt, value);
      
      if(lt->timebuff)
            {
            lt->timechangecount++;
            if(lt->timecurr)
                  {
                  lt->timecurr->next = lt->timebuff;
                  lt->timecurr = lt->timebuff;
                  }
                  else
                  {
                  lt->timehead = lt->timecurr = lt->timebuff;
                  }

            lt->timebuff=NULL;
            }
      }

return(rc);
}


int lt_emit_value_string(struct lt_trace *lt, struct lt_symbol *s, unsigned int row, char *value)
{
int rc=0;
int start_position;
int tag;

if((!lt)||(!s)||(!value)) return(rc);

if(!lt->emitted) lt->emitted = 1;

while(s->aliased_to)    /* find root alias if exists */
      {
      s=s->aliased_to;
      }

if((s->flags)&LT_SYM_F_STRING)
      {
      int numbytes;                       /* number of bytes to store value minus one */
      unsigned int last_change_delta = lt->position - s->last_change - 2;

      if(!lt->numfacs_bytes)
            {
            if(last_change_delta >= 256*65536)
                  {
                  numbytes = 3;
                  }
            else
            if(last_change_delta >= 65536)
                  {
                  numbytes = 2;
                  }
            else
            if(last_change_delta >= 256)
                  {
                  numbytes = 1;
                  }
            else
                  {
                  numbytes = 0;
                  }
      
            start_position = lt->position;
            s->last_change = start_position;

            tag = (numbytes<<4);
            lt->lt_emit_u8(lt, tag);
            switch(numbytes&3)
                  {
                  case 0: lt->lt_emit_u8(lt, last_change_delta); break;
                  case 1: lt->lt_emit_u16(lt, last_change_delta); break;
                  case 2: lt->lt_emit_u24(lt, last_change_delta); break;
                  case 3: lt->lt_emit_u32(lt, last_change_delta); break;
                  }
            }
            else
            {
            switch(lt->numfacs_bytes)
                  {
                  case 1: lt->lt_emit_u8(lt, s->facnum); break;
                  case 2: lt->lt_emit_u16(lt, s->facnum); break;
                  case 3: lt->lt_emit_u24(lt, s->facnum); break;
                  case 4: lt->lt_emit_u32(lt, s->facnum); break;
                  }
            }

      if(s->rows>0)
            {
            if(s->rows >= 256*65536)
                  {
                  numbytes = 3;
                  }
            else
            if(s->rows >= 65536)
                  {
                  numbytes = 2;
                  }
            else
            if(s->rows >= 256)
                  {
                  numbytes = 1;
                  }
            else
                  {
                  numbytes = 0;
                  }

            switch(numbytes&3)
                  {
                  case 0: lt->lt_emit_u8(lt, row); break;
                  case 1: lt->lt_emit_u16(lt, row); break;
                  case 2: lt->lt_emit_u24(lt, row); break;
                  case 3: lt->lt_emit_u32(lt, row); break;
                  }
            }

      rc=lt->lt_emit_string(lt, value);
      
      if(lt->timebuff)
            {
            lt->timechangecount++;
            if(lt->timecurr)
                  {
                  lt->timecurr->next = lt->timebuff;
                  lt->timecurr = lt->timebuff;
                  }
                  else
                  {
                  lt->timehead = lt->timecurr = lt->timebuff;
                  }

            lt->timebuff=NULL;
            }
      }

return(rc);
}


int lt_emit_value_bit_string(struct lt_trace *lt, struct lt_symbol *s, unsigned int row, char *value)
{
int rc=0;
int start_position;
int tag, tagadd;

if((!lt)||(!s)||(!value)||(!*value)) return(rc);

if(!lt->emitted) lt->emitted = 1;

while(s->aliased_to)    /* find root alias if exists */
      {
      s=s->aliased_to;
      }

if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING)))
      {
      int numbytes;                       /* number of bytes to store value minus one */
      char *pnt;
      int mvl=0;
      char ch;
      char prevch;
      unsigned int last_change_delta;

      int len = ((s->flags)&LT_SYM_F_INTEGER) ? 32 : s->len;

      if((lt->clock_compress)&&(s->rows==0))
      {
      if((len>1)&&(len<=32))
            {
            int legal = 0;
            int ivalue = 0;
            int i;
            char *pnt = value;
            int delta1, delta2;

            for(i=0;i<len;i++)
                  {
                  if((*pnt!='0')&&(*pnt!='1'))
                        {
                        if((!*pnt)&&(i>0))
                              {
                              pnt--;
                              }
                              else
                              {
                              legal = 0;
                              break;
                              }
                        }

                  ivalue = (((unsigned int)ivalue) << 1);
                  ivalue |= (*pnt & 1);
                  legal = 1;
                  pnt++;
                  }
            s->clk_mask <<= 1;
            s->clk_mask |= legal;

            if(     ((s->clk_mask&0x1f)==0x1f) && 
                  ( (delta1=(ivalue         - s->clk_prevval1) & lt_optimask[s->len]) == ((s->clk_prevval1 - s->clk_prevval3) & lt_optimask[s->len]) ) &&
                  ( (delta2=(s->clk_prevval - s->clk_prevval2) & lt_optimask[s->len]) == ((s->clk_prevval2 - s->clk_prevval4) & lt_optimask[s->len]) ) &&
                  ( (delta1==delta2) || ((!delta1)&&(!delta2)) )
                  )
                  {
                  if(s->clk_prevtrans==ULLDescriptor(~0))
                        {
                        s->clk_prevtrans = lt->timeval;
                        s->clk_numtrans = 0;
                        }
                  else
                  if(s->clk_numtrans == 0)
                        {
                        s->clk_delta = lt->timeval - s->clk_prevtrans;
                        s->clk_prevtrans = lt->timeval;
                        s->clk_numtrans++;
                        }
                  else
                        {
                        if(s->clk_delta == (lt->timeval - s->clk_prevtrans))
                              {
                              s->clk_numtrans++;
                              s->clk_prevtrans = lt->timeval;
                              if(s->clk_numtrans > LT_CLKPACK_M)
                                    {
                                    s->clk_prevval4 = s->clk_prevval3;
                                    s->clk_prevval3 = s->clk_prevval2;
                                    s->clk_prevval2 = s->clk_prevval1;
                                    s->clk_prevval1 = s->clk_prevval;
                                    s->clk_prevval  = ivalue;

                                    /* printf("Clock value '%08x' for '%s' [len=%d] at %lld (#%d)\n", 
                                          ivalue, s->name, len, lt->timeval, s->clk_numtrans); */
                                    return(1);
                                    }
                              }
                              else
                              {
                              if(s->clk_numtrans > LT_CLKPACK_M)
                                    {
                                    lt_flushclock_m(lt, s);
                                    /* flush clock then continue below! */
                                    }
                                    else
                                    {
                                    s->clk_prevtrans=ULLDescriptor(~0);
                                    }
                              }
                        }

                  }
                  else
                  {
                  if(s->clk_numtrans > LT_CLKPACK_M)
                        {
                        lt_flushclock_m(lt, s);
                        /* flush clock then continue below! */
                        }
                        else
                        {
                        s->clk_prevtrans=ULLDescriptor(~0);
                        }
                  }

            s->clk_prevval4 = s->clk_prevval3;
            s->clk_prevval3 = s->clk_prevval2;
            s->clk_prevval2 = s->clk_prevval1;
            s->clk_prevval1 = s->clk_prevval;
            s->clk_prevval  = ivalue;
            }
      else
      if(len==1) /* possible clock handling */
            {
            if(((s->clk_prevval == '1') && (value[0]=='0')) || ((s->clk_prevval == '0') && (value[0]=='1')))
                  {
                  if(s->clk_prevtrans==ULLDescriptor(~0))
                        {
                        s->clk_prevtrans = lt->timeval;
                        s->clk_numtrans = 0;
                        }
                  else
                  if(s->clk_numtrans == 0)
                        {
                        s->clk_delta = lt->timeval - s->clk_prevtrans;
                        s->clk_prevtrans = lt->timeval;
                        s->clk_numtrans++;
                        }
                  else
                        {
                        if(s->clk_delta == (lt->timeval - s->clk_prevtrans))
                              {
                              s->clk_numtrans++;
                              s->clk_prevtrans = lt->timeval;
                              if(s->clk_numtrans > LT_CLKPACK)
                                    {
                                    s->clk_prevval = value[0];

                                    /* printf("Clock value '%c' for '%s' at %lld (#%d)\n", value[0], s->name, lt->timeval, s->clk_numtrans); */
                                    return(1);
                                    }
                              }
                              else
                              {
                              if(s->clk_numtrans > LT_CLKPACK)
                                    {
                                    lt_flushclock(lt, s);
                                    /* flush clock then continue below! */
                                    }
                                    else
                                    {
                                    s->clk_prevtrans=ULLDescriptor(~0);
                                    }
                              }
                        }

                  }
                  else
                  {
                  if(s->clk_numtrans > LT_CLKPACK)
                        {
                        lt_flushclock(lt, s);
                        /* flush clock then continue below! */
                        }
                        else
                        {
                        s->clk_prevtrans=ULLDescriptor(~0);
                        }
                  }

            s->clk_prevval = value[0];
            }
      }

      /* normal trace handling */

      last_change_delta = lt->position - s->last_change - 2;

      if(last_change_delta >= 256*65536)
            {
            numbytes = 3;
            }
      else
      if(last_change_delta >= 65536)
            {
            numbytes = 2;
            }
      else
      if(last_change_delta >= 256)
            {
            numbytes = 1;
            }
      else
            {
            numbytes = 0;
            }

      pnt = value;
      prevch = *pnt;
      while((ch=*(pnt++)))
            {
            switch(ch)
                  {           
                  case '0':
                  case '1':   mvl|=LT_MVL_2; break;
                  case 'Z':   
                  case 'z':   
                  case 'X':   
                  case 'x':   mvl|=LT_MVL_4; break;
                  default:    mvl|=LT_MVL_9; break;
                  }

            if(prevch!=ch) prevch = 0;
            }

      switch(prevch)
            {           
            case 0x00:  tagadd = 0; break;
            case '0':   tagadd = 3; break;
            case '1':   tagadd = 4; break;
            case 'Z':   
            case 'z':   tagadd = 5; break;
            case 'X':   
            case 'x':   tagadd = 6; break;
            case 'H':
            case 'h':   tagadd = 7; break;
            case 'U':
            case 'u':   tagadd = 8; break;
            case 'W':
            case 'w':   tagadd = 9; break;
            case 'L':
            case 'l':   tagadd = 0xa; break;
            default:    tagadd = 0xb; break;
            }

      if(mvl)
            {
            start_position = lt->position;

            if(!lt->numfacs_bytes)
                  {
                  if(tagadd)
                        {
                        tag = (numbytes<<4) + tagadd;
                        }
                        else
                        {
                        tag = (numbytes<<4) + ((mvl&LT_MVL_9)? 2 : ((mvl&LT_MVL_4)? 1 : 0));
                        }
                  lt->lt_emit_u8(lt, tag);
                  switch(numbytes&3)
                        {
                        case 0: lt->lt_emit_u8(lt, last_change_delta); break;
                        case 1: lt->lt_emit_u16(lt, last_change_delta); break;
                        case 2: lt->lt_emit_u24(lt, last_change_delta); break;
                        case 3: lt->lt_emit_u32(lt, last_change_delta); break;
                        }
                  }
                  else
                  {
                  switch(lt->numfacs_bytes)
                        {
                        case 1: lt->lt_emit_u8(lt, s->facnum); break;
                        case 2: lt->lt_emit_u16(lt, s->facnum); break;
                        case 3: lt->lt_emit_u24(lt, s->facnum); break;
                        case 4: lt->lt_emit_u32(lt, s->facnum); break;
                        }
                  if(tagadd)
                        {
                        lt->lt_emit_u8(lt, tagadd);
                        }
                        else
                        {
                        lt->lt_emit_u8(lt, (mvl&LT_MVL_9)? 2 : ((mvl&LT_MVL_4)? 1 : 0) );
                        }
                  }

            s->last_change = start_position;

            if(s->rows>0)
                  {
                  if(s->rows >= 256*65536)
                        {
                        numbytes = 3;
                        }
                  else
                  if(s->rows >= 65536)
                        {
                        numbytes = 2;
                        }
                  else
                  if(s->rows >= 256)
                        {
                        numbytes = 1;
                        }
                  else
                        {
                        numbytes = 0;
                        }

                  switch(numbytes&3)
                        {
                        case 0: lt->lt_emit_u8(lt, row); break;
                        case 1: lt->lt_emit_u16(lt, row); break;
                        case 2: lt->lt_emit_u24(lt, row); break;
                        case 3: lt->lt_emit_u32(lt, row); break;
                        }
                  }

            if(!tagadd)
                  {
                  int len = ((s->flags)&LT_SYM_F_INTEGER) ? 32 : s->len;
                  if((mvl & (LT_MVL_2|LT_MVL_4|LT_MVL_9)) == LT_MVL_2)
                        {
                        int i;
                        int bitpos = 7;
                        int outval = 0;
                        int thisval= 0;

                        pnt = value;                        

                        if((lt->dictmode)&&(len>lt->mindictwidth))
                              {
                              char *vpnt = value;
                              while ( (*vpnt == '0') && (*(vpnt+1)) ) vpnt++;

                              lt->dict = dslxt_splay (vpnt, lt->dict);
                              if(!dslxt_success)
                                    {
                                    unsigned int vlen = strlen(vpnt)+1;
                                    char *vcopy = (char *)malloc(vlen);

                                    strcpy(vcopy, vpnt);
                                    lt->dict_string_mem_required += vlen;
                                    lt->dict = dslxt_insert(vcopy, lt->dict, lt->num_dict_entries);

                                    if(!lt->dict16_offset)
                                          {
                                          if(lt->num_dict_entries==256) lt->dict16_offset = lt->position;
                                          }
                                    else
                                    if(!lt->dict24_offset)
                                          {
                                          if(lt->num_dict_entries==65536) lt->dict24_offset = lt->position;
                                          }
                                    else
                                    if(!lt->dict32_offset)
                                          {
                                          if(lt->num_dict_entries==(256*65536)) lt->dict32_offset = lt->position;
                                          }
                  
                                    lt->num_dict_entries++;
                                    }

                              if(lt->dict24_offset)
                                    {
                                    if(lt->dict32_offset)
                                          {
                                          lt->lt_emit_u32(lt, lt->dict->val);
                                          }
                                          else
                                          {
                                          lt->lt_emit_u24(lt, lt->dict->val);
                                          }
                                    }
                              else
                                    {
                                    if(lt->dict16_offset)
                                          {
                                          lt->lt_emit_u16(lt, lt->dict->val);
                                          }
                                          else
                                          {
                                          lt->lt_emit_u8(lt, lt->dict->val);
                                          }
                                    }
                              }
                        else
                        for(i=0;i<len;i++)
                              {
                              if(*pnt)
                                    {
                                    thisval = (*pnt=='1');
                                    pnt++;
                                    }
                              outval |= (thisval<<bitpos);
                              bitpos--;
                              if((bitpos==-1)||(i==len-1))
                                    {                             
                                    lt->lt_emit_u8(lt, outval); 
                                    outval = 0;
                                    bitpos = 7;
                                    }
                              }
                        }
                  else
                  if((mvl & (LT_MVL_4|LT_MVL_9)) == LT_MVL_4)
                        {
                        int i;
                        int bitpos = 6;
                        int outval = 0;
                        int thisval= 0;

                        pnt = value;                        

                        for(i=0;i<len;i++)
                              {
                              if(*pnt)
                                    {
                                    switch(*pnt)
                                          {
                                          case '0':   thisval = 0; break;
                                          case '1':   thisval = 1; break;
                                          case 'X':
                                          case 'x':   thisval = 3; break;
                                          default:    thisval = 2; break;
                                          }
                                    pnt++;
                                    }
                              outval |= (thisval<<bitpos);
                              bitpos-=2;
                              if((bitpos==-2)||(i==len-1))
                                    {                             
                                    lt->lt_emit_u8(lt, outval); 
                                    outval = 0;
                                    bitpos = 6;
                                    }
                              }
                        }
                  else
                  /* if(mvl & LT_MVL_9) */
                        {
                        int i;
                        int bitpos = 4;
                        int outval = 0;
                        int thisval= 0;

                        pnt = value;                        

                        for(i=0;i<len;i++)
                              {
                              if(*pnt)
                                    {
                                    switch(*pnt)
                                          {
                                          case '0':   thisval = 0; break;
                                          case '1':   thisval = 1; break;
                                          case 'Z':
                                          case 'z':   thisval = 2; break;
                                          case 'X':
                                          case 'x':   thisval = 3; break;
                                          case 'H':
                                          case 'h':   thisval = 4; break;
                                          case 'U':
                                          case 'u':   thisval = 5; break;
                                          case 'W':
                                          case 'w':   thisval = 6; break;
                                          case 'L':
                                          case 'l':   thisval = 7; break;
                                          default:    thisval = 8; break;
                                          }
                                    pnt++;
                                    }
                              outval |= (thisval<<bitpos);
                              bitpos-=4;
                              if((bitpos==-4)||(i==len-1))
                                    {                             
                                    lt->lt_emit_u8(lt, outval); 
                                    outval = 0;
                                    bitpos = 4;
                                    }
                              }
                        }
                  }

            rc=1;
            }
      
      if(lt->timebuff)
            {
            lt->timechangecount++;
            if(lt->timecurr)
                  {
                  lt->timecurr->next = lt->timebuff;
                  lt->timecurr = lt->timebuff;
                  }
                  else
                  {
                  lt->timehead = lt->timecurr = lt->timebuff;
                  }

            lt->timebuff=NULL;
            }
      }

return(rc);
}


/*
 * blackout functions
 */
void lt_set_dumpoff(struct lt_trace *lt)
{
if((lt)&&(!lt->dumpoff_active))
      {
      struct lt_timetrail *ltt = calloc(1, sizeof(struct lt_timetrail));

      ltt->timeval = lt->timeval;
      if(lt->dumpoffhead)
            {
            lt->dumpoffcurr->next = ltt;
            lt->dumpoffcurr = ltt;
            }
            else
            {
            lt->dumpoffhead = lt->dumpoffcurr = ltt;
            }

      lt->dumpoff_active = 1;
      lt->dumpoffcount++;
      }
}

void lt_set_dumpon(struct lt_trace *lt)
{
if((lt)&&(lt->dumpoff_active))
      {
      struct lt_timetrail *ltt = calloc(1, sizeof(struct lt_timetrail));

      ltt->timeval = lt->timeval;

      lt->dumpoffcurr->next = ltt;
      lt->dumpoffcurr = ltt;

      lt->dumpoff_active = 0;
      }
}

Generated by  Doxygen 1.6.0   Back to index