/*
 * Copyright (c) Tony Bybell 2001-2014.
 *
 * 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; either version 2
 * of the License, or (at your option) any later version.
 */

#include <config.h>
#include <stdio.h>
#include "zlib.h"
#include "bzlib.h"

#if !defined __MINGW32__ && !defined _MSC_VER
#include <unistd.h>
#include <sys/mman.h>
#else
#include <windows.h>
#include <io.h>
#endif

#include"globals.h"
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "symbol.h"
#include "vcd.h"
#include "lxt.h"
#include "bsearch.h"
#include "debug.h"
#include "hierpack.h"

/****************************************************************************/

/*
 * functions which emit various big endian
 * data to a file
 */

static int lt_emit_u8(FILE *handle, int value)
{
unsigned char buf[1];
int nmemb;

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


static int lt_emit_u16(FILE *handle, int value)
{
unsigned char buf[2];
int nmemb;

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


static int lt_emit_u24(FILE *handle, 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, handle);
GLOBALS->fpos_lxt_c_1+=nmemb;
return(nmemb);
}


static int lt_emit_u32(FILE *handle, 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, handle);
GLOBALS->fpos_lxt_c_1+=nmemb;
return(nmemb);
}

/****************************************************************************/

#define LXTHDR "LXTLOAD | "



				/* its mmap() variant doesn't use file descriptors    */
#if defined __MINGW32__ || defined _MSC_VER
#define PROT_READ (0)
#define MAP_SHARED (0)

HANDLE hIn, hInMap;

char *win_fname = NULL;

void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
{
close(fd);
hIn = CreateFile(win_fname, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hIn == INVALID_HANDLE_VALUE)
{
	fprintf(stderr, "Could not open '%s' with CreateFile(), exiting.\n", win_fname);
	exit(255);
}

hInMap = CreateFileMapping(hIn, NULL, PAGE_READONLY, 0, 0, NULL);
return(MapViewOfFile(hInMap, FILE_MAP_READ, 0, 0, 0));
}

int munmap(void *start, size_t length)
{
UnmapViewOfFile(start);
CloseHandle(hInMap); hInMap = NULL;
CloseHandle(hIn); hIn = NULL;
return(0);
}


#endif

/****************************************************************************/

#ifdef _WAVE_BE32

/*
 * reconstruct 8/16/24/32 bits out of the lxt's representation
 * of a big-endian integer.  this is for 32-bit PPC so no byte
 * swizzling needs to be done at all.  for 24-bit ints, we have no danger of
 * running off the end of memory provided we do the "-1" trick
 * since we'll never read a 24-bit int at the very start of a file which
 * means that we'll have a 32-bit word that we can read.
 */

inline static unsigned int get_byte(offset) {
  return ((unsigned int)(*((unsigned char *)(GLOBALS->mm_lxt_c_1)+(offset))));
}

inline static unsigned int get_16(offset) {
  return ((unsigned int)(*((unsigned short *)(((unsigned char *)(GLOBALS->mm_lxt_c_1))
                +(offset)))));
}

inline static unsigned int get_32(offset) {
  return (*(unsigned int *)(((unsigned char *)(GLOBALS->mm_lxt_c_1))+(offset)));
}

inline static unsigned int get_24(offset) {
  return ((get_32((offset)-1)<<8)>>8);
}

inline static unsigned int get_64(offset) {
  return ((((UTimeType)get_32(offset))<<32)|((UTimeType)get_32((offset)+4)));
}

#else

/*
 * reconstruct 8/16/24/32 bits out of the lxt's representation
 * of a big-endian integer.  this should work on all architectures.
 */
#define get_byte(offset) 	((unsigned int)(*((unsigned char *)GLOBALS->mm_lxt_c_1+offset)))

static unsigned int get_16(off_t offset)
{
unsigned char *nn=(unsigned char *)GLOBALS->mm_lxt_c_1+offset;
unsigned int m1=*((unsigned char *)(nn++));
unsigned int m2=*((unsigned char *)nn);
return((m1<<8)|m2);
}

static unsigned int get_24(off_t offset)
{
unsigned char *nn=(unsigned char *)GLOBALS->mm_lxt_c_1+offset;
unsigned int m1=*((unsigned char *)(nn++));
unsigned int m2=*((unsigned char *)(nn++));
unsigned int m3=*((unsigned char *)nn);
return((m1<<16)|(m2<<8)|m3);
}

static unsigned int get_32(off_t offset)
{
unsigned char *nn=(unsigned char *)GLOBALS->mm_lxt_c_1+offset;
unsigned int m1=*((unsigned char *)(nn++));
unsigned int m2=*((unsigned char *)(nn++));
unsigned int m3=*((unsigned char *)(nn++));
unsigned int m4=*((unsigned char *)nn);
return((m1<<24)|(m2<<16)|(m3<<8)|m4);
}

static UTimeType get_64(off_t offset)
{
return(
(((UTimeType)get_32(offset))<<32)
|((UTimeType)get_32(offset+4))
);
}

#endif

/****************************************************************************/


static void create_double_endian_mask(int offset)
{
double d;
int i, j;
static double p = 3.14159;

d= *((double *)((unsigned char *)GLOBALS->mm_lxt_c_1+offset));
if(p==d)
	{
	GLOBALS->double_is_native_lxt_c_1=1;
	}
	else
	{
	char *remote, *here;

	remote = (char *)&d;
	here = (char *)&p;
	for(i=0;i<8;i++)
		{
		for(j=0;j<8;j++)
			{
			if(here[i]==remote[j])
				{
				GLOBALS->double_mask_lxt_c_1[i]=j;
				break;
				}
			}
		}
	}
}

static char *swab_double_via_mask(int offset)
{
char swapbuf[8];
char *pnt = malloc_2(8*sizeof(char));
int i;

memcpy(swapbuf, ((unsigned char *)GLOBALS->mm_lxt_c_1+offset), 8);
for(i=0;i<8;i++)
	{
	pnt[i]=swapbuf[GLOBALS->double_mask_lxt_c_1[i]];
	}

return(pnt);
}

/****************************************************************************/

/*
 * convert 0123 to an mvl character representation
 */
static unsigned char convert_mvl(int value)
{
return("01zxhuwl-xxxxxxx"[value&15]);
}


/*
 * given an offset into the aet, calculate the "time" of that
 * offset in simulation.  this func similar to how gtkwave can
 * find the most recent valuechange that corresponds with
 * an arbitrary timevalue.
 */
static int compar_mvl_timechain(const void *s1, const void *s2)
{
int key, obj, delta;
int rv;

key=*((int *)s1);
obj=*((int *)s2);

if((obj<=key)&&(obj>GLOBALS->max_compare_time_tc_lxt_c_2))
        {
        GLOBALS->max_compare_time_tc_lxt_c_2=obj;
        GLOBALS->max_compare_pos_tc_lxt_c_2=(int *)s2 - GLOBALS->positional_information_lxt_c_1;
        }

delta=key-obj;
if(delta<0) rv=-1;
else if(delta>0) rv=1;
else rv=0;

return(rv);
}

static TimeType bsearch_mvl_timechain(int key)
{
GLOBALS->max_compare_time_tc_lxt_c_2=-1; GLOBALS->max_compare_pos_tc_lxt_c_2=-1;

if(bsearch((void *)&key, (void *)GLOBALS->positional_information_lxt_c_1, GLOBALS->total_cycles_lxt_c_2, sizeof(int), compar_mvl_timechain))
	{
	/* nothing, all side effects are in bsearch */
	}

if((GLOBALS->max_compare_pos_tc_lxt_c_2<=0)||(GLOBALS->max_compare_time_tc_lxt_c_2<0))
        {
        GLOBALS->max_compare_pos_tc_lxt_c_2=0; /* aix bsearch fix */
        }

return(GLOBALS->time_information[GLOBALS->max_compare_pos_tc_lxt_c_2]);
}


/*
 * build up decompression dictionary for MVL2 facs >16 bits ...
 */
static void build_dict(void)
{
gzFile zhandle;
off_t offs = GLOBALS->zdictionary_offset_lxt_c_1+24;
int total_mem, rc;
unsigned int i;
char *decmem=NULL;
char *pnt;
#if defined __MINGW32__ || defined _MSC_VER
FILE *tmp;
#endif

GLOBALS->dict_num_entries_lxt_c_1 = get_32(GLOBALS->zdictionary_offset_lxt_c_1+0);
GLOBALS->dict_string_mem_required_lxt_c_1 = get_32(GLOBALS->zdictionary_offset_lxt_c_1+4);
GLOBALS->dict_16_offset_lxt_c_1 = get_32(GLOBALS->zdictionary_offset_lxt_c_1+8);
GLOBALS->dict_24_offset_lxt_c_1 = get_32(GLOBALS->zdictionary_offset_lxt_c_1+12);
GLOBALS->dict_32_offset_lxt_c_1 = get_32(GLOBALS->zdictionary_offset_lxt_c_1+16);
GLOBALS->dict_width_lxt_c_1 = get_32(GLOBALS->zdictionary_offset_lxt_c_1+20);

DEBUG(fprintf(stderr, LXTHDR"zdictionary_offset = %08x\n", GLOBALS->zdictionary_offset_lxt_c_1));
DEBUG(fprintf(stderr, LXTHDR"zdictionary_predec_size = %08x\n\n", GLOBALS->zdictionary_predec_size_lxt_c_1));
DEBUG(fprintf(stderr, LXTHDR"dict_num_entries = %d\n", GLOBALS->dict_num_entries_lxt_c_1));
DEBUG(fprintf(stderr, LXTHDR"dict_string_mem_required = %d\n", GLOBALS->dict_string_mem_required_lxt_c_1));
DEBUG(fprintf(stderr, LXTHDR"dict_16_offset = %d\n", GLOBALS->dict_16_offset_lxt_c_1));
DEBUG(fprintf(stderr, LXTHDR"dict_24_offset = %d\n", GLOBALS->dict_24_offset_lxt_c_1));
DEBUG(fprintf(stderr, LXTHDR"dict_32_offset = %d\n", GLOBALS->dict_32_offset_lxt_c_1));

fprintf(stderr, LXTHDR"Dictionary compressed MVL2 change records detected...\n");

#if defined __MINGW32__ || defined _MSC_VER
{
unsigned char *t = (char *)GLOBALS->mm_lxt_c_1+offs;
tmp = tmpfile(); if(!tmp) { fprintf(stderr, LXTHDR"could not open decompression tempfile, exiting.\n"); exit(255); }
fwrite(t, GLOBALS->zdictionary_predec_size_lxt_c_1, 1, tmp); fseek(tmp, 0, SEEK_SET);
zhandle = gzdopen(dup(fileno(tmp)), "rb");
}
#else
if(offs!=lseek(GLOBALS->fd_lxt_c_1, offs, SEEK_SET)) { fprintf(stderr, LXTHDR"dict lseek error at offset %08x\n", (unsigned int)offs); exit(255); }
zhandle = gzdopen(dup(GLOBALS->fd_lxt_c_1), "rb");
#endif
decmem = malloc_2(total_mem = GLOBALS->dict_string_mem_required_lxt_c_1);

rc=gzread(zhandle, decmem, total_mem);
DEBUG(printf(LXTHDR"section offs for name decompression = %08x of len %d\n", offs, GLOBALS->dict_num_entries_lxt_c_1));
DEBUG(printf(LXTHDR"Decompressed size is %d bytes (vs %d)\n", rc, total_mem));
if(rc!=total_mem) { fprintf(stderr, LXTHDR"decompression size disparity  %d bytes (vs %d)\n", rc, total_mem); exit(255); }

GLOBALS->dict_string_mem_array_lxt_c_1 = (char **)calloc_2(GLOBALS->dict_num_entries_lxt_c_1, sizeof(char *));
pnt = decmem;
for(i=0;i<GLOBALS->dict_num_entries_lxt_c_1;i++)
	{
	GLOBALS->dict_string_mem_array_lxt_c_1[i]=pnt;
	pnt+=(strlen(pnt)+1);
	DEBUG(printf(LXTHDR"Dict %d: '1%s'\n", i, GLOBALS->dict_string_mem_array_lxt_c_1[i]));
	}

gzclose(zhandle);
#if defined __MINGW32__ || defined _MSC_VER
fclose(tmp);
#endif

fprintf(stderr, LXTHDR"...expanded %d entries from %08x into %08x bytes.\n", GLOBALS->dict_num_entries_lxt_c_1, GLOBALS->zdictionary_predec_size_lxt_c_1, GLOBALS->dict_string_mem_required_lxt_c_1);
}


/*
 * decompress facility names and build up fac geometry
 */
static void build_facs(char *fname, char **f_name, struct Node *node_block)
{
char *buf, *bufprev = NULL, *bufcurr;
off_t offs=GLOBALS->facname_offset_lxt_c_1+8;
int i, j, clone;
char *pnt = NULL;
int total_mem = get_32(GLOBALS->facname_offset_lxt_c_1+4);
gzFile zhandle = NULL;
char *decmem=NULL;

#if defined __MINGW32__ || defined _MSC_VER
FILE *tmp;
#endif

buf=malloc_2(total_mem);
pnt=bufprev=buf;

if(GLOBALS->zfacname_size_lxt_c_1)
	{
	int rc;
#if defined __MINGW32__ || defined _MSC_VER
	unsigned char *t = (char *)GLOBALS->mm_lxt_c_1+offs;
	tmp = tmpfile(); if(!tmp) { fprintf(stderr, LXTHDR"could not open decompression tempfile, exiting.\n"); exit(255); }
	fwrite(t, GLOBALS->zfacname_size_lxt_c_1, 1, tmp); fseek(tmp, 0, SEEK_SET);
	zhandle = gzdopen(dup(fileno(tmp)), "rb");
#else
	if(offs!=lseek(GLOBALS->fd_lxt_c_1, offs, SEEK_SET)) { fprintf(stderr, LXTHDR"zfacname lseek error at offset %08x\n", (unsigned int)offs); exit(255); }
	zhandle = gzdopen(dup(GLOBALS->fd_lxt_c_1), "rb");
#endif

	GLOBALS->mmcache_lxt_c_1 = GLOBALS->mm_lxt_c_1;
	decmem = malloc_2(total_mem = GLOBALS->zfacname_predec_size_lxt_c_1); GLOBALS->mm_lxt_c_1 = decmem;

	rc=gzread(zhandle, decmem, total_mem);
	DEBUG(printf(LXTHDR"section offs for name decompression = %08x of len %d\n", offs, GLOBALS->zfacname_size_lxt_c_1));
	DEBUG(printf(LXTHDR"Decompressed size is %d bytes (vs %d)\n", rc, total_mem));
	if(rc!=total_mem) { fprintf(stderr, LXTHDR"decompression size disparity  %d bytes (vs %d)\n", rc, total_mem); exit(255); }

	offs=0;	/* we're in our new memory region now.. */
	}

fprintf(stderr, LXTHDR"Building %d facilities.\n", GLOBALS->numfacs);
for(i=0;i<GLOBALS->numfacs;i++)
	{
        clone=get_16(offs);  offs+=2;
	bufcurr=pnt;
	for(j=0;j<clone;j++)
		{
		*(pnt++) = *(bufprev++);
		}
        while((*(pnt++)=get_byte(offs++)));
        f_name[i]=bufcurr;
	DEBUG(printf(LXTHDR"Encountered facility %d: '%s'\n", i, bufcurr));
	bufprev=bufcurr;
        }

if(GLOBALS->zfacname_size_lxt_c_1)
	{
	GLOBALS->mm_lxt_c_1 = GLOBALS->mmcache_lxt_c_1;
	free_2(decmem); decmem = NULL;
	gzclose(zhandle);
#if defined __MINGW32__ ||  defined _MSC_VER
	fclose(tmp);
#endif
	}

if(!GLOBALS->facgeometry_offset_lxt_c_1)
	{
	fprintf(stderr, "LXT '%s' is missing a facility geometry section, exiting.\n", fname);
	exit(255);
	}

offs=GLOBALS->facgeometry_offset_lxt_c_1;

if(GLOBALS->zfacgeometry_size_lxt_c_1)
	{
	int rc;

#if defined __MINGW32__ || defined _MSC_VER
	unsigned char *t = (char *)GLOBALS->mm_lxt_c_1+offs;
	tmp = tmpfile(); if(!tmp) { fprintf(stderr, LXTHDR"could not open decompression tempfile, exiting.\n"); exit(255); }
	fwrite(t, GLOBALS->zfacgeometry_size_lxt_c_1, 1, tmp); fseek(tmp, 0, SEEK_SET);
	zhandle = gzdopen(dup(fileno(tmp)), "rb");
#else
	if(offs!=lseek(GLOBALS->fd_lxt_c_1, offs, SEEK_SET)) { fprintf(stderr, LXTHDR"zfacgeometry lseek error at offset %08x\n", (unsigned int)offs); exit(255); }
	zhandle = gzdopen(dup(GLOBALS->fd_lxt_c_1), "rb");
#endif
	GLOBALS->mmcache_lxt_c_1 = GLOBALS->mm_lxt_c_1;
	total_mem = GLOBALS->numfacs * 16;
	decmem = malloc_2(total_mem); GLOBALS->mm_lxt_c_1 = decmem;

	rc=gzread(zhandle, decmem, total_mem);
	DEBUG(printf(LXTHDR"section offs for facgeometry decompression = %08x of len %d\n", offs, GLOBALS->zfacgeometry_size_lxt_c_1));
	DEBUG(printf(LXTHDR"Decompressed size is %d bytes (vs %d)\n", rc, total_mem));
	if(rc!=total_mem) { fprintf(stderr, LXTHDR"decompression size disparity  %d bytes (vs %d)\n", rc, total_mem); exit(255); }

	offs=0;	/* we're in our new memory region now.. */
	}

for(i=0;i<GLOBALS->numfacs;i++)
	{
	GLOBALS->mvlfacs_lxt_c_2[i].node_alias=get_32(offs);
	node_block[i].msi=get_32(offs+4);
	node_block[i].lsi=get_32(offs+8);
	GLOBALS->mvlfacs_lxt_c_2[i].flags=get_32(offs+12);
	GLOBALS->mvlfacs_lxt_c_2[i].len=(node_block[i].lsi>node_block[i].msi)?(node_block[i].lsi-node_block[i].msi+1):(node_block[i].msi-node_block[i].lsi+1);

	if(GLOBALS->mvlfacs_lxt_c_2[i].len>GLOBALS->lt_len_lxt_c_1) GLOBALS->lt_len_lxt_c_1 = GLOBALS->mvlfacs_lxt_c_2[i].len;
	DEBUG(printf(LXTHDR"%s[%d:%d]\n", f_name[i], node_block[i].msi, node_block[i].lsi));

	offs+=0x10;
	}

GLOBALS->lt_buf_lxt_c_1 = malloc_2(GLOBALS->lt_len_lxt_c_1>255 ? GLOBALS->lt_len_lxt_c_1 : 256);	/* in order to keep trivial LXT files from overflowing their buffer */

if(GLOBALS->zfacgeometry_size_lxt_c_1)
	{
	GLOBALS->mm_lxt_c_1 = GLOBALS->mmcache_lxt_c_1;
	free_2(decmem); decmem = NULL;
	gzclose(zhandle);
#if defined __MINGW32__ || defined _MSC_VER
	fclose(tmp);
#endif
	}
}


/*
 * build up the lastchange entries so we can start to walk
 * through the aet..
 */
static void build_facs2(char *fname)
{
int i;
off_t offs;
int chg;
int maxchg=0, maxindx=0;
int last_position;
TimeType last_time;
char *decmem = NULL;
int total_mem;
gzFile zhandle = NULL;

#if defined __MINGW32__ || defined _MSC_VER
FILE *tmp;
#endif

if((!GLOBALS->time_table_offset_lxt_c_1)&&(!GLOBALS->time_table_offset64_lxt_c_1))
	{
	fprintf(stderr, "LXT '%s' is missing a time table section, exiting.\n", fname);
	exit(255);
	}

if((GLOBALS->time_table_offset_lxt_c_1)&&(GLOBALS->time_table_offset64_lxt_c_1))
	{
	fprintf(stderr, "LXT '%s' has both 32 and 64-bit time table sections, exiting.\n", fname);
	exit(255);
	}

if(GLOBALS->time_table_offset_lxt_c_1)
	{
	offs = GLOBALS->time_table_offset_lxt_c_1;

	DEBUG(printf(LXTHDR"Time table position: %08x\n", GLOBALS->time_table_offset_lxt_c_1 + 12));
	GLOBALS->total_cycles_lxt_c_2=get_32(offs+0);
	DEBUG(printf(LXTHDR"Total cycles: %d\n", GLOBALS->total_cycles_lxt_c_2));

	if(GLOBALS->ztime_table_size_lxt_c_1)
		{
		int rc;

#if defined __MINGW32__ || defined _MSC_VER
		unsigned char *t = (char *)GLOBALS->mm_lxt_c_1+offs+4;
		tmp = tmpfile(); if(!tmp) { fprintf(stderr, LXTHDR"could not open decompression tempfile, exiting.\n"); exit(255); }
		fwrite(t, GLOBALS->ztime_table_size_lxt_c_1, 1, tmp); fseek(tmp, 0, SEEK_SET);
		zhandle = gzdopen(dup(fileno(tmp)), "rb");
#else
		if((offs+4)!=lseek(GLOBALS->fd_lxt_c_1, offs+4, SEEK_SET)) { fprintf(stderr, LXTHDR"ztime_table lseek error at offset %08x\n", (unsigned int)offs); exit(255); }
		zhandle = gzdopen(dup(GLOBALS->fd_lxt_c_1), "rb");
#endif
		GLOBALS->mmcache_lxt_c_1 = GLOBALS->mm_lxt_c_1;
		total_mem = 4 + 4 + (GLOBALS->total_cycles_lxt_c_2 * 4) + (GLOBALS->total_cycles_lxt_c_2 * 4);
		decmem = malloc_2(total_mem); GLOBALS->mm_lxt_c_1 = decmem;

		rc=gzread(zhandle, decmem, total_mem);
		DEBUG(printf(LXTHDR"section offs for timetable decompression = %08x of len %d\n", offs, GLOBALS->ztime_table_size_lxt_c_1));
		DEBUG(printf(LXTHDR"Decompressed size is %d bytes (vs %d)\n", rc, total_mem));
		if(rc!=total_mem) { fprintf(stderr, LXTHDR"decompression size disparity  %d bytes (vs %d)\n", rc, total_mem); exit(255); }

		offs=0;	/* we're in our new memory region now.. */
		}
		else
		{
		offs+=4; /* skip past count to make consistent view between compressed/uncompressed */
		}

	GLOBALS->first_cycle_lxt_c_2=get_32(offs);
	DEBUG(printf(LXTHDR"First cycle: %d\n", GLOBALS->first_cycle_lxt_c_2));
	GLOBALS->last_cycle_lxt_c_2=get_32(offs+4);
	DEBUG(printf(LXTHDR"Last cycle: %d\n", GLOBALS->last_cycle_lxt_c_2));
	DEBUG(printf(LXTHDR"Total cycles (actual): %d\n", GLOBALS->last_cycle_lxt_c_2-GLOBALS->first_cycle_lxt_c_2+1));

	/* rebuild time table from its deltas... */

	GLOBALS->positional_information_lxt_c_1 = (int *)malloc_2(GLOBALS->total_cycles_lxt_c_2 * sizeof(int));
	last_position=0;
	offs+=8;
	for(i=0;i<GLOBALS->total_cycles_lxt_c_2;i++)
		{
		last_position = GLOBALS->positional_information_lxt_c_1[i] = get_32(offs) + last_position;
		offs+=4;
		}
	GLOBALS->time_information =       (TimeType *)malloc_2(GLOBALS->total_cycles_lxt_c_2 * sizeof(TimeType));
	last_time=LLDescriptor(0);
	for(i=0;i<GLOBALS->total_cycles_lxt_c_2;i++)
		{
		last_time = GLOBALS->time_information[i] = ((TimeType)get_32(offs)) + last_time;
		GLOBALS->time_information[i] *= (GLOBALS->time_scale);
		offs+=4;
		}

	if(GLOBALS->ztime_table_size_lxt_c_1)
		{
		GLOBALS->mm_lxt_c_1 = GLOBALS->mmcache_lxt_c_1;
		free_2(decmem); decmem = NULL;
		gzclose(zhandle);
#if defined __MINGW32__ || defined _MSC_VER
		fclose(tmp);
#endif
		}
	}
	else	/* 64-bit read */
	{
	offs = GLOBALS->time_table_offset64_lxt_c_1;

	DEBUG(printf(LXTHDR"Time table position: %08x\n", GLOBALS->time_table_offset64_lxt_c_1 + 20));

	GLOBALS->total_cycles_lxt_c_2=(TimeType)((unsigned int)get_32(offs+0));
	DEBUG(printf(LXTHDR"Total cycles: %d\n", GLOBALS->total_cycles_lxt_c_2));

	if(GLOBALS->ztime_table_size_lxt_c_1)
		{
		int rc;

#if defined __MINGW32__ || defined _MSC_VER
		unsigned char *t = (char *)GLOBALS->mm_lxt_c_1+offs+4;
		tmp = tmpfile(); if(!tmp) { fprintf(stderr, LXTHDR"could not open decompression tempfile, exiting.\n"); exit(255); }
		fwrite(t, GLOBALS->ztime_table_size_lxt_c_1, 1, tmp); fseek(tmp, 0, SEEK_SET);
		zhandle = gzdopen(dup(fileno(tmp)), "rb");
#else
		if((offs+4)!=lseek(GLOBALS->fd_lxt_c_1, offs+4, SEEK_SET)) { fprintf(stderr, LXTHDR"ztime_table lseek error at offset %08x\n", (unsigned int)offs); exit(255); }
		zhandle = gzdopen(dup(GLOBALS->fd_lxt_c_1), "rb");
#endif
		GLOBALS->mmcache_lxt_c_1 = GLOBALS->mm_lxt_c_1;
		total_mem = 8 + 8 + (GLOBALS->total_cycles_lxt_c_2 * 4) + (GLOBALS->total_cycles_lxt_c_2 * 8);
		decmem = malloc_2(total_mem); GLOBALS->mm_lxt_c_1 = decmem;

		rc=gzread(zhandle, decmem, total_mem);
		DEBUG(printf(LXTHDR"section offs for timetable decompression = %08x of len %d\n", offs, GLOBALS->ztime_table_size_lxt_c_1));
		DEBUG(printf(LXTHDR"Decompressed size is %d bytes (vs %d)\n", rc, total_mem));
		if(rc!=total_mem) { fprintf(stderr, LXTHDR"decompression size disparity  %d bytes (vs %d)\n", rc, total_mem); exit(255); }

		offs=0;	/* we're in our new memory region now.. */
		}
		else
		{
		offs+=4; /* skip past count to make consistent view between compressed/uncompressed */
		}

	GLOBALS->first_cycle_lxt_c_2=get_64(offs);
	DEBUG(printf(LXTHDR"First cycle: %d\n", GLOBALS->first_cycle_lxt_c_2));
	GLOBALS->last_cycle_lxt_c_2=get_64(offs+8);
	DEBUG(printf(LXTHDR"Last cycle: %d\n", GLOBALS->last_cycle_lxt_c_2));
	DEBUG(printf(LXTHDR"Total cycles (actual): %lld\n", GLOBALS->last_cycle_lxt_c_2-GLOBALS->first_cycle_lxt_c_2+1));

	/* rebuild time table from its deltas... */

	GLOBALS->positional_information_lxt_c_1 = (int *)malloc_2(GLOBALS->total_cycles_lxt_c_2 * sizeof(int));
	last_position=0;
	offs+=16;
	for(i=0;i<GLOBALS->total_cycles_lxt_c_2;i++)
		{
		last_position = GLOBALS->positional_information_lxt_c_1[i] = get_32(offs) + last_position;
		offs+=4;
		}
	GLOBALS->time_information =       (TimeType *)malloc_2(GLOBALS->total_cycles_lxt_c_2 * sizeof(TimeType));
	last_time=LLDescriptor(0);
	for(i=0;i<GLOBALS->total_cycles_lxt_c_2;i++)
		{
		last_time = GLOBALS->time_information[i] = ((TimeType)get_64(offs)) + last_time;
		GLOBALS->time_information[i] *= (GLOBALS->time_scale);
		offs+=8;
		}

	if(GLOBALS->ztime_table_size_lxt_c_1)
		{
		GLOBALS->mm_lxt_c_1 = GLOBALS->mmcache_lxt_c_1;
		free_2(decmem); decmem = NULL;
		gzclose(zhandle);
#if defined __MINGW32__ || defined _MSC_VER
		fclose(tmp);
#endif
		}
	}

if(GLOBALS->sync_table_offset_lxt_c_1)
	{
	offs = GLOBALS->sync_table_offset_lxt_c_1;

	if(GLOBALS->zsync_table_size_lxt_c_1)
		{
		int rc;
#if defined __MINGW32__ || defined _MSC_VER
		unsigned char *t = (char *)GLOBALS->mm_lxt_c_1+offs;
		tmp = tmpfile(); if(!tmp) { fprintf(stderr, LXTHDR"could not open decompression tempfile, exiting.\n"); exit(255); }
		fwrite(t, GLOBALS->zsync_table_size_lxt_c_1, 1, tmp); fseek(tmp, 0, SEEK_SET);
		zhandle = gzdopen(dup(fileno(tmp)), "rb");
#else
		if(offs!=lseek(GLOBALS->fd_lxt_c_1, offs, SEEK_SET)) { fprintf(stderr, LXTHDR"zsync_table lseek error at offset %08x\n", (unsigned int)offs); exit(255); }
		zhandle = gzdopen(dup(GLOBALS->fd_lxt_c_1), "rb");
#endif
		GLOBALS->mmcache_lxt_c_1 = GLOBALS->mm_lxt_c_1;
		decmem = malloc_2(total_mem = GLOBALS->numfacs * 4); GLOBALS->mm_lxt_c_1 = decmem;

		rc=gzread(zhandle, decmem, total_mem);
		DEBUG(printf(LXTHDR"section offs for synctable decompression = %08x of len %d\n", offs, GLOBALS->zsync_table_size_lxt_c_1));
		DEBUG(printf(LXTHDR"Decompressed size is %d bytes (vs %d)\n", rc, total_mem));
		if(rc!=total_mem) { fprintf(stderr, LXTHDR"decompression size disparity  %d bytes (vs %d)\n", rc, total_mem); exit(255); }

		offs=0;	/* we're in our new memory region now.. */
		}

	for(i=0;i<GLOBALS->numfacs;i++)
		{
		chg=get_32(offs);  offs+=4;
		if(chg>maxchg) {maxchg=chg; maxindx=i; }
		GLOBALS->lastchange[i]=chg;
		}

	if(GLOBALS->zsync_table_size_lxt_c_1)
		{
		GLOBALS->mm_lxt_c_1 = GLOBALS->mmcache_lxt_c_1;
		free_2(decmem); decmem = NULL;
		gzclose(zhandle);
#if defined __MINGW32__ || defined _MSC_VER
		fclose(tmp);
#endif
		}

	GLOBALS->maxchange_lxt_c_1=maxchg;
	GLOBALS->maxindex_lxt_c_1=maxindx;
	}

if(GLOBALS->zchg_size_lxt_c_1)
	{
	/* we don't implement the tempfile version for windows... */
#if !defined __MINGW32__ && !defined _MSC_VER
	if(GLOBALS->zchg_predec_size_lxt_c_1 > LXT_MMAP_MALLOC_BOUNDARY)
		{
		int fd_dummy;
		char *nam = tmpnam_2(NULL, &fd_dummy);
		FILE *tmp = fopen(nam, "wb");
		unsigned int len=GLOBALS->zchg_predec_size_lxt_c_1;
		int rc;
		char buf[32768];
		int fd2 = open(nam, O_RDONLY);
		char testbyte[2]={0,0};
		char is_bz2;

		unlink(nam);
		if(fd_dummy >=0) close(fd_dummy);

		fprintf(stderr, LXTHDR"Compressed change records detected, making tempfile...\n");
		if(GLOBALS->change_field_offset_lxt_c_1 != lseek(GLOBALS->fd_lxt_c_1, GLOBALS->change_field_offset_lxt_c_1, SEEK_SET)) { fprintf(stderr, LXTHDR"lseek error at offset %08x\n", (unsigned int)GLOBALS->change_field_offset_lxt_c_1); exit(255); }

		is_bz2 = (read(GLOBALS->fd_lxt_c_1, &testbyte, 2))&&(testbyte[0]=='B')&&(testbyte[1]=='Z');

		if(GLOBALS->change_field_offset_lxt_c_1 != lseek(GLOBALS->fd_lxt_c_1, GLOBALS->change_field_offset_lxt_c_1, SEEK_SET)) { fprintf(stderr, LXTHDR"lseek error at offset %08x\n", (unsigned int)GLOBALS->change_field_offset_lxt_c_1); exit(255); }

		if(is_bz2)
			{
			zhandle = BZ2_bzdopen(dup(GLOBALS->fd_lxt_c_1), "rb");

			while(len)
				{
				int siz = (len>32768) ? 32768 : len;
				rc = BZ2_bzread(zhandle, buf, siz);
				if(rc!=siz) { fprintf(stderr, LXTHDR"gzread error to tempfile %d (act) vs %d (exp), exiting.\n", rc, siz); exit(255); }
				if(1 != fwrite(buf, siz, 1, tmp)) { fprintf(stderr, LXTHDR"fwrite error to tempfile, exiting.\n"); exit(255); };
				len -= siz;
				}

			fprintf(stderr, LXTHDR"...expanded %08x into %08x bytes.\n", GLOBALS->zchg_size_lxt_c_1, GLOBALS->zchg_predec_size_lxt_c_1);
			BZ2_bzclose(zhandle);
			}
			else
			{
			zhandle = gzdopen(dup(GLOBALS->fd_lxt_c_1), "rb");

			while(len)
				{
				int siz = (len>32768) ? 32768 : len;
				rc = gzread(zhandle, buf, siz);
				if(rc!=siz) { fprintf(stderr, LXTHDR"gzread error to tempfile %d (act) vs %d (exp), exiting.\n", rc, siz); exit(255); }
				if(1 != fwrite(buf, siz, 1, tmp)) { fprintf(stderr, LXTHDR"fwrite error to tempfile, exiting.\n"); exit(255); };
				len -= siz;
				}

			fprintf(stderr, LXTHDR"...expanded %08x into %08x bytes.\n", GLOBALS->zchg_size_lxt_c_1, GLOBALS->zchg_predec_size_lxt_c_1);
			gzclose(zhandle);
			}
		munmap(GLOBALS->mm_lxt_c_1, GLOBALS->f_len_lxt_c_1); close(GLOBALS->fd_lxt_c_1);
		fflush(tmp);
		fseeko(tmp, 0, SEEK_SET);
		fclose(tmp);

		GLOBALS->fd_lxt_c_1 = fd2;
		GLOBALS->mm_lxt_c_1=mmap(NULL, GLOBALS->zchg_predec_size_lxt_c_1, PROT_READ, MAP_SHARED, GLOBALS->fd_lxt_c_1, 0);
		GLOBALS->mm_lxt_mmap_addr = GLOBALS->mm_lxt_c_1;
		GLOBALS->mm_lxt_mmap_len = GLOBALS->zchg_predec_size_lxt_c_1;
		GLOBALS->mm_lxt_c_1=(void *)((char *)GLOBALS->mm_lxt_c_1-4); /* because header and version don't exist in packed change records */
		}
		else
#endif
		{
		unsigned int len=GLOBALS->zchg_predec_size_lxt_c_1;
		int rc;
		char *buf = malloc_2(GLOBALS->zchg_predec_size_lxt_c_1);
		char *pnt = buf;
		char testbyte[2]={0,0};
		char is_bz2;

		fprintf(stderr, LXTHDR"Compressed change records detected...\n");
#if defined __MINGW32__ || defined _MSC_VER
		{
		unsigned char *t = (char *)GLOBALS->mm_lxt_c_1+GLOBALS->change_field_offset_lxt_c_1;
		tmp = tmpfile(); if(!tmp) { fprintf(stderr, LXTHDR"could not open decompression tempfile, exiting.\n"); exit(255); }
		fwrite(t, GLOBALS->zchg_size_lxt_c_1, 1, tmp); fseek(tmp, 0, SEEK_SET);
		is_bz2 = (get_byte(GLOBALS->change_field_offset_lxt_c_1)=='B') && (get_byte(GLOBALS->change_field_offset_lxt_c_1+1)=='Z');
		}
#else
		if(GLOBALS->change_field_offset_lxt_c_1 != lseek(GLOBALS->fd_lxt_c_1, GLOBALS->change_field_offset_lxt_c_1, SEEK_SET)) { fprintf(stderr, LXTHDR"lseek error at offset %08x\n", (unsigned int)GLOBALS->change_field_offset_lxt_c_1); exit(255); }

		is_bz2 = (read(GLOBALS->fd_lxt_c_1, &testbyte, 2))&&(testbyte[0]=='B')&&(testbyte[1]=='Z');

		if(GLOBALS->change_field_offset_lxt_c_1 != lseek(GLOBALS->fd_lxt_c_1, GLOBALS->change_field_offset_lxt_c_1, SEEK_SET)) { fprintf(stderr, LXTHDR"lseek error at offset %08x\n", (unsigned int)GLOBALS->change_field_offset_lxt_c_1); exit(255); }
#endif

		if(is_bz2)
			{
#if defined __MINGW32__ || defined _MSC_VER
			zhandle = BZ2_bzdopen(dup(fileno(tmp)), "rb");
#else
			zhandle = BZ2_bzdopen(dup(GLOBALS->fd_lxt_c_1), "rb");
#endif

			while(len)
				{
				int siz = (len>32768) ? 32768 : len;
				rc = BZ2_bzread(zhandle, pnt, siz);
				if(rc!=siz) { fprintf(stderr, LXTHDR"BZ2_bzread error to buffer %d (act) vs %d (exp), exiting.\n", rc, siz); exit(255); }
				pnt += siz;
				len -= siz;
				}

			fprintf(stderr, LXTHDR"...expanded %08x into %08x bytes.\n", GLOBALS->zchg_size_lxt_c_1, GLOBALS->zchg_predec_size_lxt_c_1);
			BZ2_bzclose(zhandle);
			}
			else
			{
#if defined __MINGW32__ || defined _MSC_VER
			zhandle = gzdopen(dup(fileno(tmp)), "rb");
#else
			zhandle = gzdopen(dup(GLOBALS->fd_lxt_c_1), "rb");
#endif
			while(len)
				{
				int siz = (len>32768) ? 32768 : len;
				rc = gzread(zhandle, pnt, siz);
				if(rc!=siz) { fprintf(stderr, LXTHDR"gzread error to buffer %d (act) vs %d (exp), exiting.\n", rc, siz); exit(255); }
				pnt += siz;
				len -= siz;
				}

			fprintf(stderr, LXTHDR"...expanded %08x into %08x bytes.\n", GLOBALS->zchg_size_lxt_c_1, GLOBALS->zchg_predec_size_lxt_c_1);
			gzclose(zhandle);
#if defined __MINGW32__ || defined _MSC_VER
			fclose(tmp);
#endif
			}

		munmap(GLOBALS->mm_lxt_c_1, GLOBALS->f_len_lxt_c_1);
#if !defined __MINGW32__ && !defined _MSC_VER
		close(GLOBALS->fd_lxt_c_1);
#endif

		GLOBALS->fd_lxt_c_1=-1;
		GLOBALS->mm_lxt_c_1=buf-4; /* because header and version don't exist in packed change records */
		}
	}


if(!GLOBALS->sync_table_offset_lxt_c_1)
	{
	off_t vlen = GLOBALS->zchg_predec_size_lxt_c_1 ? GLOBALS->zchg_predec_size_lxt_c_1+4 : 0;
	unsigned int numfacs_bytes;
	unsigned int num_records = 0;
	unsigned int last_change_delta, numbytes;
	int *positional_compar = GLOBALS->positional_information_lxt_c_1;
        int *positional_kill_pnt = GLOBALS->positional_information_lxt_c_1 + GLOBALS->total_cycles_lxt_c_2;
        char positional_kill = 0;

	unsigned int dict_16_offset_new = 0;
	unsigned int dict_24_offset_new = 0;
	unsigned int dict_32_offset_new = 0;

	char *nam;
	FILE *tmp;
	int recfd;
	int fd_dummy;

	offs = GLOBALS->zchg_predec_size_lxt_c_1 ? 4 : 0;
	fprintf(stderr, LXTHDR"Linear LXT encountered...\n");

	if(!GLOBALS->zchg_predec_size_lxt_c_1)
		{
		fprintf(stderr, LXTHDR"Uncompressed linear LXT not supported, exiting.\n");
		exit(255);
		}

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

	nam = tmpnam_2(NULL, &fd_dummy);
	tmp = fopen(nam, "wb");
	GLOBALS->fpos_lxt_c_1 = 4;	/* fake 4 bytes padding */
	recfd = open(nam, O_RDONLY);

	unlink(nam);
	if(fd_dummy >=0) close(fd_dummy);


	while(offs < vlen)
		{
		int facidx = 0;
		unsigned char cmd;
		off_t offscache2, offscache3;
		unsigned int height;
		unsigned char cmdkill;

		num_records++;

                /* remake time vs position table on the fly */
                if(!positional_kill)
                        {
                        if(offs == *positional_compar)
                                {
                                *positional_compar = GLOBALS->fpos_lxt_c_1;
                                positional_compar++;
                                if(positional_compar == positional_kill_pnt) positional_kill = 1;
                                }
                        }

		switch(numfacs_bytes&3)
			{
			case 0: facidx = get_byte(offs); break;
			case 1: facidx = get_16(offs); break;
			case 2: facidx = get_24(offs); break;
			case 3: facidx = get_32(offs); break;
			}

		if(facidx>GLOBALS->numfacs)
			{
			fprintf(stderr, LXTHDR"Facidx %d out of range (vs %d) at offset %08x, exiting.\n", facidx, GLOBALS->numfacs, (unsigned int)offs);
			exit(255);
			}

		offs += (numfacs_bytes+1);

		cmdkill = GLOBALS->mvlfacs_lxt_c_2[facidx].flags & (LT_SYM_F_DOUBLE|LT_SYM_F_STRING);
		if(!cmdkill)
			{
			cmd = get_byte(offs);

			if(cmd>0xf)
				{
				fprintf(stderr, LXTHDR"Command byte %02x invalid at offset %08x, exiting.\n", cmd, (unsigned int)offs);
				exit(0);
				}

			offs++;
			}
			else
			{
			cmd=0;
			}

		offscache2 = offs;

		height = GLOBALS->mvlfacs_lxt_c_2[facidx].node_alias;
		if(height)
			{
			if(height >= 256*65536)
			        {
			        offs += 4;
			        }
			else
			if(height >= 65536)
			        {
			        offs += 3;
			        }
			else
			if(height >= 256)
			        {
			        offs += 2;
			        }
			else
			        {
			        offs += 1;
			        }
			}


		offscache3 = offs;
		if(!dict_16_offset_new)
			{
			if (offs == GLOBALS->dict_16_offset_lxt_c_1) { dict_16_offset_new = GLOBALS->fpos_lxt_c_1; }
			}
		else
		if(!dict_24_offset_new)
			{
			if (offs == GLOBALS->dict_24_offset_lxt_c_1) { dict_24_offset_new = GLOBALS->fpos_lxt_c_1; }
			}
		else
		if(!dict_32_offset_new)
			{
			if (offs == GLOBALS->dict_32_offset_lxt_c_1) { dict_32_offset_new = GLOBALS->fpos_lxt_c_1; }
			}


		/* printf("%08x : %04x %02x (%d) %s[%d:%d]\n", offscache, facidx, cmd, mvlfacs[facidx].len, mvlfacs[facidx].f_name, mvlfacs[facidx].msb, mvlfacs[facidx].lsb); */

		if(!cmdkill)
		switch(cmd)
			{
			unsigned int modlen;
			case 0x0:
			modlen = (!(GLOBALS->mvlfacs_lxt_c_2[facidx].flags&LT_SYM_F_INTEGER)) ? GLOBALS->mvlfacs_lxt_c_2[facidx].len : 32;
			if((GLOBALS->dict_string_mem_array_lxt_c_1) && (modlen>GLOBALS->dict_width_lxt_c_1))
				{
				if((!GLOBALS->dict_16_offset_lxt_c_1)||(offscache3<GLOBALS->dict_16_offset_lxt_c_1))
					{
					offs += 1;
					}
				else
				if((!GLOBALS->dict_24_offset_lxt_c_1)||(offscache3<GLOBALS->dict_24_offset_lxt_c_1))
					{
					offs += 2;
					}
				else
				if((!GLOBALS->dict_32_offset_lxt_c_1)||(offscache3<GLOBALS->dict_32_offset_lxt_c_1))
					{
					offs += 3;
					}
				else
					{
					offs += 4;
					}
				}
				else
				{
				offs += (modlen + 7)/8; /* was offs += (GLOBALS->mvlfacs_lxt_c_2[facidx].len + 7)/8 which is wrong for integers! */
				}

			break;


			case 0x1:
					offs += (GLOBALS->mvlfacs_lxt_c_2[facidx].len + 3)/4;
					break;

			case 0x2:
					offs += (GLOBALS->mvlfacs_lxt_c_2[facidx].len + 1)/2;
					break;

			case 0x3:
			case 0x4:
			case 0x5:
			case 0x6:
			case 0x7:
			case 0x8:
			case 0x9:
			case 0xa:
			case 0xb:	break;	/* single byte, no extra "skip" */


			case 0xc:
			case 0xd:
			case 0xe:
			case 0xf:	offs += ((cmd&3)+1);	/* skip past numbytes_trans */
					break;
			}
		else
			{
			/* cmdkill = 1 for strings + reals skip bytes */
			if(GLOBALS->mvlfacs_lxt_c_2[facidx].flags & LT_SYM_F_DOUBLE)
				{
				offs += 8;
				}
				else	/* strings */
				{
				while(get_byte(offs)) offs++;
				offs++;
				}
			}

		last_change_delta = GLOBALS->fpos_lxt_c_1 - GLOBALS->lastchange[facidx] - 2;
		GLOBALS->lastchange[facidx] = GLOBALS->fpos_lxt_c_1;

		GLOBALS->maxchange_lxt_c_1=GLOBALS->fpos_lxt_c_1;
		GLOBALS->maxindex_lxt_c_1=facidx;

        	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;
                	}

		lt_emit_u8(tmp, (numbytes<<4) | cmd);
	        switch(numbytes&3)
	                {
	                case 0: lt_emit_u8(tmp, last_change_delta); break;
	                case 1: lt_emit_u16(tmp, last_change_delta); break;
	                case 2: lt_emit_u24(tmp, last_change_delta); break;
	                case 3: lt_emit_u32(tmp, last_change_delta); break;
                	}

		if(offs-offscache2)
			{
			GLOBALS->fpos_lxt_c_1 += fwrite((char *)GLOBALS->mm_lxt_c_1+offscache2, 1, offs-offscache2, tmp);	/* copy rest of relevant info */
			}
		}

	GLOBALS->dict_16_offset_lxt_c_1 = dict_16_offset_new;
	GLOBALS->dict_24_offset_lxt_c_1 = dict_24_offset_new;
	GLOBALS->dict_32_offset_lxt_c_1 = dict_32_offset_new;

        fflush(tmp);
        fseeko(tmp, 0, SEEK_SET);
        fclose(tmp);
	fprintf(stderr, LXTHDR"%d linear records converted into %08x bytes.\n", num_records, GLOBALS->fpos_lxt_c_1-4);

#if !defined __MINGW32__ && !defined _MSC_VER
	if(GLOBALS->zchg_predec_size_lxt_c_1 > LXT_MMAP_MALLOC_BOUNDARY)
		{
		munmap((char *)GLOBALS->mm_lxt_c_1+4, GLOBALS->zchg_predec_size_lxt_c_1); close(GLOBALS->fd_lxt_c_1);
		GLOBALS->mm_lxt_mmap_addr = NULL;
		GLOBALS->mm_lxt_mmap_len = 0;
		}
		else
#endif
		{
		free_2((char *)GLOBALS->mm_lxt_c_1+4);
		}

	GLOBALS->fd_lxt_c_1 = recfd;
#if defined __MINGW32__ || defined _MSC_VER
	win_fname = nam;
#endif
        GLOBALS->mm_lxt_c_1=mmap(NULL, GLOBALS->fpos_lxt_c_1-4, PROT_READ, MAP_SHARED, recfd, 0);
	GLOBALS->mm_lxt_mmap_addr = GLOBALS->mm_lxt_c_1;
	GLOBALS->mm_lxt_mmap_len = GLOBALS->fpos_lxt_c_1-4;
        GLOBALS->mm_lxt_c_1=(void *)((char *)GLOBALS->mm_lxt_c_1-4); /* because header and version don't exist in packed change records */
	}
}


/*
 * given a fac+offset, return the binary data for it
 */
static char *parse_offset(struct fac *which, off_t offs)
{
int v, v2;
unsigned int j;
int k;
unsigned int l;
char *pnt;
char repeat;

l=which->len;
pnt = GLOBALS->lt_buf_lxt_c_1;
v=get_byte(offs);
v2=v&0x0f;

switch(v2)
	{
	case 0x00:	/* MVL2 */
			{
			unsigned int msk;
			unsigned int bitcnt=0;
			int ch;

			if((GLOBALS->dict_string_mem_array_lxt_c_1) && (l>GLOBALS->dict_width_lxt_c_1))
				{
				unsigned int dictpos;
				unsigned int ld;

				offs += ((v>>4)&3)+2;	/* skip value */

				if((!GLOBALS->dict_16_offset_lxt_c_1)||(offs<GLOBALS->dict_16_offset_lxt_c_1))
					{
					dictpos = get_byte(offs);
					}
				else
				if((!GLOBALS->dict_24_offset_lxt_c_1)||(offs<GLOBALS->dict_24_offset_lxt_c_1))
					{
					dictpos = get_16(offs);
					}
				else
				if((!GLOBALS->dict_32_offset_lxt_c_1)||(offs<GLOBALS->dict_32_offset_lxt_c_1))
					{
					dictpos = get_24(offs);
					}
				else
					{
					dictpos = get_32(offs);
					}

				if(dictpos <= GLOBALS->dict_num_entries_lxt_c_1)
					{
					ld = strlen(GLOBALS->dict_string_mem_array_lxt_c_1[dictpos]);
					for(j=0;j<(l-(ld+1));j++)
						{
						*(pnt++) = '0';
						}
					*(pnt++) = '1';
					memcpy(pnt, GLOBALS->dict_string_mem_array_lxt_c_1[dictpos], ld);
					}
					else
					{
					fprintf(stderr, LXTHDR"dict entry at offset %08x [%d] out of range, ignoring!\n", dictpos, (unsigned int)offs);
					for(j=0;j<l;j++)
						{
						*(pnt++) = '0';
						}
					}
				}
				else
				{
				offs += ((v>>4)&3)+2;	/* skip value */
				for(j=0;;j++)
					{
					ch=get_byte(offs+j);
					msk=0x80;
					for(k=0;k<8;k++)
						{
						*(pnt++)= (ch&msk) ? '1' : '0';
						msk>>=1;
						bitcnt++;
						if(bitcnt==l) goto bail;
						}
					}
				}
			}
			break;

	case 0x01:	/* MVL4 */
			{
			unsigned int bitcnt=0;
			int ch;
			int rsh;

			offs += ((v>>4)&3)+2;	/* skip value */
			for(j=0;;j++)
				{
				ch=get_byte(offs+j);
				rsh=6;
				for(k=0;k<4;k++)
					{
					*(pnt++)=convert_mvl((ch>>rsh)&0x3);
					rsh-=2;
					bitcnt++;
					if(bitcnt==l) goto bail;
					}
				}
			}
			break;

	case 0x02:	/* MVL9 */
			{
			unsigned int bitcnt=0;
			int ch;
			int rsh;

			offs += ((v>>4)&3)+2;	/* skip value */
			for(j=0;;j++)
				{
				ch=get_byte(offs+j);
				rsh=4;
				for(k=0;k<2;k++)
					{
					*(pnt++)=convert_mvl(ch>>rsh);
					rsh-=4;
					bitcnt++;
					if(bitcnt==l) goto bail;
					}
				}
			}
			break;

	case 0x03:	/* mvl repeat expansions */
	case 0x04:
	case 0x05:
	case 0x06:
	case 0x07:
	case 0x08:
	case 0x09:
	case 0x0a:
	case 0x0b:
			repeat = convert_mvl(v2-3);
			for(j=0;j<l;j++)
				{
				*(pnt++)=repeat;
				}
			break;

	default:
			fprintf(stderr, LXTHDR"Unknown %02x at offset: %08x\n", v, (unsigned int)offs);
			exit(255);
	}

bail:
return(GLOBALS->lt_buf_lxt_c_1);
}


/*
 * mainline
 */
TimeType lxt_main(char *fname)
{
int i;
struct Node *n;
struct symbol *s, *prevsymroot=NULL, *prevsym=NULL;
off_t tagpnt;
int tag;
struct symbol *sym_block = NULL;
struct Node *node_block = NULL;
char **f_name = NULL;

GLOBALS->fd_lxt_c_1=open(fname, O_RDONLY);
if(GLOBALS->fd_lxt_c_1<0)
        {
        fprintf(stderr, "Could not open '%s', exiting.\n", fname);
        vcd_exit(255);
        }

GLOBALS->f_len_lxt_c_1=lseek(GLOBALS->fd_lxt_c_1, (off_t)0, SEEK_END);
#if defined __MINGW32__ || defined _MSC_VER
win_fname = fname;
#endif
GLOBALS->mm_lxt_c_1=mmap(NULL, GLOBALS->f_len_lxt_c_1, PROT_READ, MAP_SHARED, GLOBALS->fd_lxt_c_1, 0);
GLOBALS->mm_lxt_mmap_addr = GLOBALS->mm_lxt_c_1;
GLOBALS->mm_lxt_mmap_len = GLOBALS->f_len_lxt_c_1;

if(get_16((off_t)0)!=LT_HDRID) /* scan-build, assign to i= from get_16 removed */
	{
	fprintf(stderr, "Not an LXT format AET, exiting.\n");
	vcd_exit(255);
	}

if((GLOBALS->version_lxt_c_1=get_16((off_t)2))>LT_VERSION)
	{
	fprintf(stderr, "Version %d of LXT format AETs not supported, exiting.\n", GLOBALS->version_lxt_c_1);
	vcd_exit(255);
	}

if(get_byte(GLOBALS->f_len_lxt_c_1-1)!=LT_TRLID)
	{
	fprintf(stderr, "LXT '%s' is truncated, exiting.\n", fname);
	vcd_exit(255);
	}

DEBUG(printf(LXTHDR"Loading LXT '%s'...\n", fname));
DEBUG(printf(LXTHDR"Len: %d\n", (unsigned int)GLOBALS->f_len_lxt_c_1));

/* SPLASH */                            splash_create();

tagpnt = GLOBALS->f_len_lxt_c_1-2;
while((tag=get_byte(tagpnt))!=LT_SECTION_END)
	{
	off_t offset = get_32(tagpnt-4);
	tagpnt-=5;

	switch(tag)
		{
		case LT_SECTION_CHG:			GLOBALS->change_field_offset_lxt_c_1=offset; DEBUG(printf(LXTHDR"LT_SECTION_CHG at %08x\n", offset)); break;
		case LT_SECTION_SYNC_TABLE:		GLOBALS->sync_table_offset_lxt_c_1=offset; DEBUG(printf(LXTHDR"LT_SECTION_SYNC_TABLE at %08x\n", offset)); break;
		case LT_SECTION_FACNAME:		GLOBALS->facname_offset_lxt_c_1=offset; DEBUG(printf(LXTHDR"LT_SECTION_FACNAME at %08x\n", offset)); break;
		case LT_SECTION_FACNAME_GEOMETRY:	GLOBALS->facgeometry_offset_lxt_c_1=offset; DEBUG(printf(LXTHDR"LT_SECTION_FACNAME_GEOMETRY at %08x\n", offset)); break;
		case LT_SECTION_TIMESCALE:		GLOBALS->timescale_offset_lxt_c_1=offset; DEBUG(printf(LXTHDR"LT_SECTION_TIMESCALE at %08x\n", offset)); break;
		case LT_SECTION_TIME_TABLE:		GLOBALS->time_table_offset_lxt_c_1=offset; DEBUG(printf(LXTHDR"LT_SECTION_TIME_TABLE at %08x\n", offset)); break;
		case LT_SECTION_TIME_TABLE64:		GLOBALS->time_table_offset64_lxt_c_1=offset; DEBUG(printf(LXTHDR"LT_SECTION_TIME_TABLE64 at %08x\n", offset)); break;
		case LT_SECTION_INITIAL_VALUE:		GLOBALS->initial_value_offset_lxt_c_1=offset; DEBUG(printf(LXTHDR"LT_SECTION_INITIAL_VALUE at %08x\n", offset)); break;
		case LT_SECTION_DOUBLE_TEST:		GLOBALS->double_test_offset_lxt_c_1=offset; DEBUG(printf(LXTHDR"LT_SECTION_DOUBLE_TEST at %08x\n", offset)); break;

		case LT_SECTION_ZFACNAME_PREDEC_SIZE:	GLOBALS->zfacname_predec_size_lxt_c_1=offset; DEBUG(printf(LXTHDR"LT_SECTION_ZFACNAME_PREDEC_SIZE = %08x\n", offset)); break;
		case LT_SECTION_ZFACNAME_SIZE:		GLOBALS->zfacname_size_lxt_c_1=offset; DEBUG(printf(LXTHDR"LT_SECTION_ZFACNAME_SIZE = %08x\n", offset)); break;
		case LT_SECTION_ZFACNAME_GEOMETRY_SIZE:	GLOBALS->zfacgeometry_size_lxt_c_1=offset; DEBUG(printf(LXTHDR"LT_SECTION_ZFACNAME_GEOMETRY_SIZE = %08x\n", offset)); break;
		case LT_SECTION_ZSYNC_SIZE:		GLOBALS->zsync_table_size_lxt_c_1=offset; DEBUG(printf(LXTHDR"LT_SECTION_ZSYNC_SIZE = %08x\n", offset)); break;
		case LT_SECTION_ZTIME_TABLE_SIZE:	GLOBALS->ztime_table_size_lxt_c_1=offset; DEBUG(printf(LXTHDR"LT_SECTION_ZTIME_TABLE_SIZE = %08x\n", offset)); break;
		case LT_SECTION_ZCHG_PREDEC_SIZE:	GLOBALS->zchg_predec_size_lxt_c_1=offset; DEBUG(printf(LXTHDR"LT_SECTION_ZCHG_PREDEC_SIZE = %08x\n", offset)); break;
		case LT_SECTION_ZCHG_SIZE:		GLOBALS->zchg_size_lxt_c_1=offset; DEBUG(printf(LXTHDR"LT_SECTION_ZCHG_SIZE = %08x\n", offset)); break;

		case LT_SECTION_ZDICTIONARY:		GLOBALS->zdictionary_offset_lxt_c_1=offset; DEBUG(printf(LXTHDR"LT_SECTION_ZDICTIONARY = %08x\n", offset)); break;
		case LT_SECTION_ZDICTIONARY_SIZE:	GLOBALS->zdictionary_predec_size_lxt_c_1=offset; DEBUG(printf(LXTHDR"LT_SECTION_ZDICTIONARY_SIZE = %08x\n", offset)); break;

		case LT_SECTION_EXCLUDE_TABLE:		GLOBALS->exclude_offset_lxt_c_1=offset; DEBUG(printf(LXTHDR"LT_SECTION_EXCLUDE_TABLE = %08x\n", offset)); break;

		case LT_SECTION_TIMEZERO:		GLOBALS->lxt_timezero_offset=offset; DEBUG(printf(LXTHDR"LT_SECTION_TIMEZERO = %08x\n", offset)); break;

		default: fprintf(stderr, "Skipping unknown section tag %02x.\n", tag); break;
		}
	}

if(GLOBALS->lxt_timezero_offset)
	{
	GLOBALS->global_time_offset = get_64(GLOBALS->lxt_timezero_offset);
	}

if(GLOBALS->exclude_offset_lxt_c_1)
	{
	off_t offset = GLOBALS->exclude_offset_lxt_c_1;
	int ix, num_blackouts = get_32(offset);
	TimeType bs, be;
	struct blackout_region_t *bt;

	offset+=4;

	for(ix=0;ix<num_blackouts;ix++)
		{
		bs = get_64(offset); offset+=8;
		be = get_64(offset); offset+=8;

		bt = calloc_2(1, sizeof(struct blackout_region_t));
		bt->bstart = bs;
		bt->bend = be;

		bt->next = GLOBALS->blackout_regions;

		GLOBALS->blackout_regions = bt;
		}
	}

if(GLOBALS->double_test_offset_lxt_c_1)
	{
	create_double_endian_mask(GLOBALS->double_test_offset_lxt_c_1);
	}

if(GLOBALS->timescale_offset_lxt_c_1)
	{
	signed char scale;

	scale=(signed char)get_byte(GLOBALS->timescale_offset_lxt_c_1);
	exponent_to_time_scale(scale);
	}
	else
	{
	GLOBALS->time_dimension = 'n';
	}

if(!GLOBALS->facname_offset_lxt_c_1)
	{
	fprintf(stderr, "LXT '%s' is missing a facility name section, exiting.\n", fname);
	vcd_exit(255);
	}

GLOBALS->numfacs=get_32(GLOBALS->facname_offset_lxt_c_1);
DEBUG(printf(LXTHDR"Number of facs: %d\n", GLOBALS->numfacs));
GLOBALS->mvlfacs_lxt_c_2=(struct fac *)calloc_2(GLOBALS->numfacs,sizeof(struct fac));
GLOBALS->resolve_lxt_alias_to=(struct Node **)calloc_2(GLOBALS->numfacs,sizeof(struct Node *));
GLOBALS->lastchange=(unsigned int *)calloc_2(GLOBALS->numfacs,sizeof(unsigned int));
f_name = calloc_2(GLOBALS->numfacs,sizeof(char *));

if(GLOBALS->initial_value_offset_lxt_c_1)
	{
	switch(get_byte(GLOBALS->initial_value_offset_lxt_c_1))
		{
                case 0:         GLOBALS->initial_value_lxt_c_1 = AN_0; break;
                case 1:         GLOBALS->initial_value_lxt_c_1 = AN_1; break;
                case 2:         GLOBALS->initial_value_lxt_c_1 = AN_Z; break;
                case 4:         GLOBALS->initial_value_lxt_c_1 = AN_H; break;
                case 5:         GLOBALS->initial_value_lxt_c_1 = AN_U; break;
                case 6:         GLOBALS->initial_value_lxt_c_1 = AN_W; break;
                case 7:         GLOBALS->initial_value_lxt_c_1 = AN_L; break;
                case 8:         GLOBALS->initial_value_lxt_c_1 = AN_DASH; break;
		default:	GLOBALS->initial_value_lxt_c_1 = AN_X; break;
		}
	}
	else
	{
	GLOBALS->initial_value_lxt_c_1 = AN_X;
	}


if(GLOBALS->zdictionary_offset_lxt_c_1)
	{
	if(GLOBALS->zdictionary_predec_size_lxt_c_1)
		{
		build_dict();
		}
		else
		{
		fprintf(stderr, "LXT '%s' is missing a zdictionary_predec_size chunk, exiting.\n", fname);
		vcd_exit(255);
		}
	}

sym_block = (struct symbol *)calloc_2(GLOBALS->numfacs, sizeof(struct symbol));
node_block = (struct Node *)calloc_2(GLOBALS->numfacs,sizeof(struct Node));

build_facs(fname, f_name, node_block);
/* SPLASH */                            splash_sync(1, 5);
build_facs2(fname);
/* SPLASH */                            splash_sync(2, 5);

/* do your stuff here..all useful info has been initialized by now */

if(!GLOBALS->hier_was_explicitly_set)    /* set default hierarchy split char */
        {
        GLOBALS->hier_delimeter='.';
        }

for(i=0;i<GLOBALS->numfacs;i++)
        {
	char buf[4096];
	char *str;
	struct fac *f;

	if(GLOBALS->mvlfacs_lxt_c_2[i].flags&LT_SYM_F_ALIAS)
		{
		int alias = GLOBALS->mvlfacs_lxt_c_2[i].node_alias;
		f=GLOBALS->mvlfacs_lxt_c_2+alias;

		while(f->flags&LT_SYM_F_ALIAS)
			{
			f=GLOBALS->mvlfacs_lxt_c_2+f->node_alias;
			}
		}
		else
		{
		f=GLOBALS->mvlfacs_lxt_c_2+i;
		}

	if((f->len>1)&& (!(f->flags&(LT_SYM_F_INTEGER|LT_SYM_F_DOUBLE|LT_SYM_F_STRING))) )
		{
		int len = sprintf(buf, "%s[%d:%d]", f_name[i],node_block[i].msi, node_block[i].lsi);
		str=malloc_2(len+1);
		if(!GLOBALS->alt_hier_delimeter)
			{
			strcpy(str, buf);
			}
			else
			{
			strcpy_vcdalt(str, buf, GLOBALS->alt_hier_delimeter);
			}
                s=&sym_block[i];
                symadd_name_exists_sym_exists(s,str,0);
		prevsymroot = prevsym = NULL;
		}
		else
		{
		int gatecmp = (f->len==1) && (!(f->flags&(LT_SYM_F_INTEGER|LT_SYM_F_DOUBLE|LT_SYM_F_STRING))) && (node_block[i].msi!=-1) && (node_block[i].lsi!=-1);
		int revcmp = gatecmp && (i) && (!strcmp(f_name[i], f_name[i-1]));

		if(gatecmp)
			{
			int len = sprintf(buf, "%s[%d]", f_name[i],node_block[i].msi);
			str=malloc_2(len+1);
			if(!GLOBALS->alt_hier_delimeter)
				{
				strcpy(str, buf);
				}
				else
				{
				strcpy_vcdalt(str, buf, GLOBALS->alt_hier_delimeter);
				}
	                s=&sym_block[i];
	                symadd_name_exists_sym_exists(s,str,0);
			if((prevsym)&&(revcmp)&&(!strchr(f_name[i], '\\'))) /* allow chaining for search functions.. */
				{
				prevsym->vec_root = prevsymroot;
				prevsym->vec_chain = s;
				s->vec_root = prevsymroot;
				prevsym = s;
				}
				else
				{
				prevsymroot = prevsym = s;
				}
			}
			else
			{
			str=malloc_2(strlen(f_name[i])+1);
			if(!GLOBALS->alt_hier_delimeter)
				{
				strcpy(str, f_name[i]);
				}
				else
				{
				strcpy_vcdalt(str, f_name[i], GLOBALS->alt_hier_delimeter);
				}
	                s=&sym_block[i];
	                symadd_name_exists_sym_exists(s,str,0);
			prevsymroot = prevsym = NULL;

			if(f->flags&LT_SYM_F_INTEGER)
				{
				node_block[i].msi=31;
				node_block[i].lsi=0;
				GLOBALS->mvlfacs_lxt_c_2[i].len=32;
				}
			}
		}

	n=&node_block[i];
        n->nname=s->name;
        n->mv.mvlfac = GLOBALS->mvlfacs_lxt_c_2+i;

	if((f->len>1)||(f->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING)))
		{
		n->extvals = 1;
		}

        n->head.time=-1;        /* mark 1st node as negative time */
        n->head.v.h_val=AN_X;
        s->n=n;
        }

free_2(f_name[0]);	/* the start of the big decompression buffer */
for(i=0;i<GLOBALS->numfacs;i++)
	{
	f_name[i] = NULL;
	}
free_2(f_name); f_name = NULL;

/* SPLASH */                            splash_sync(3, 5);
GLOBALS->facs=(struct symbol **)malloc_2(GLOBALS->numfacs*sizeof(struct symbol *));
for(i=0;i<GLOBALS->numfacs;i++)
	{
	char *subst, ch;
	int len;
	int esc = 0;

	GLOBALS->facs[i]=&sym_block[i];
        if((len=strlen(subst=GLOBALS->facs[i]->name))>GLOBALS->longestname) GLOBALS->longestname=len;
	while((ch=(*subst)))
		{
#ifdef WAVE_HIERFIX
		if(ch==GLOBALS->hier_delimeter) { *subst=(!esc) ? VCDNAM_HIERSORT : VCDNAM_ESCAPE; }	/* forces sort at hier boundaries */
#else
                if((ch==GLOBALS->hier_delimeter)&&(esc)) { *subst = VCDNAM_ESCAPE; }    /* forces sort at hier boundaries */
#endif
		else if(ch=='\\') { esc = 1; GLOBALS->escaped_names_found_vcd_c_1 = 1; }
		subst++;
		}
	}

fprintf(stderr, LXTHDR"Sorting facilities at hierarchy boundaries...");
wave_heapsort(GLOBALS->facs,GLOBALS->numfacs);
fprintf(stderr, "sorted.\n");

#ifdef WAVE_HIERFIX
for(i=0;i<GLOBALS->numfacs;i++)
	{
	char *subst, ch;

	subst=GLOBALS->facs[i]->name;
	while((ch=(*subst)))
		{
		if(ch==VCDNAM_HIERSORT) { *subst=GLOBALS->hier_delimeter; }	/* restore back to normal */
		subst++;
		}

#ifdef DEBUG_FACILITIES
	printf("%-4d %s\n",i,facs[i]->name);
#endif
	}
#endif

GLOBALS->facs_are_sorted=1;

fprintf(stderr, LXTHDR"Building facility hierarchy tree...");
/* SPLASH */                            splash_sync(4, 5);
init_tree();
for(i=0;i<GLOBALS->numfacs;i++)
{
char *nf = GLOBALS->facs[i]->name;
build_tree_from_name(nf, i);
}
/* SPLASH */                            splash_sync(5, 5);

if(GLOBALS->escaped_names_found_vcd_c_1)
	{
	for(i=0;i<GLOBALS->numfacs;i++)
		{
		char *subst, ch;

		subst=GLOBALS->facs[i]->name;
		while((ch=(*subst)))
			{
			if(ch==VCDNAM_ESCAPE) { *subst=GLOBALS->hier_delimeter; }	/* restore back to normal */
			subst++;
			}

#ifdef DEBUG_FACILITIES
		printf("%-4d %s\n",i,facs[i]->name);
#endif
		}
	}

treegraft(&GLOBALS->treeroot);
treesort(GLOBALS->treeroot, NULL);

if(GLOBALS->escaped_names_found_vcd_c_1)
        {
        treenamefix(GLOBALS->treeroot);
        }

fprintf(stderr, "built.\n\n");

#ifdef DEBUG_FACILITIES
treedebug(GLOBALS->treeroot,"");
#endif

GLOBALS->min_time = GLOBALS->first_cycle_lxt_c_2*GLOBALS->time_scale; GLOBALS->max_time=GLOBALS->last_cycle_lxt_c_2*GLOBALS->time_scale;
fprintf(stderr, "["TTFormat"] start time.\n["TTFormat"] end time.\n", GLOBALS->min_time, GLOBALS->max_time);
GLOBALS->is_lxt = ~0;

if(GLOBALS->blackout_regions)
        {
        struct blackout_region_t *bt = GLOBALS->blackout_regions;
        while(bt)
                {
                bt->bstart *= GLOBALS->time_scale;
                bt->bend *= GLOBALS->time_scale;
                bt = bt->next;
                }
        }

/* SPLASH */                            splash_finalize();
return(GLOBALS->max_time);
}


/*
 * this is the black magic that handles aliased signals...
 */
static void lxt_resolver(nptr np, nptr resolve)
{
np->extvals = resolve->extvals;
np->msi = resolve->msi;
np->lsi = resolve->lsi;
memcpy(&np->head, &resolve->head, sizeof(struct HistEnt));
np->curr = resolve->curr;
np->harray = resolve->harray;
np->numhist = resolve->numhist;
np->mv.mvlfac=NULL;
}


/*
 * actually import an lxt trace but don't do it if
 * 1) it's already been imported
 * 2) an alias of this trace has been imported--instead
 *    copy over the relevant info and be done with it.
 */
void import_lxt_trace(nptr np)
{
off_t offs, offsdelta;
int v, w;
TimeType tmval;
TimeType prevtmval;
struct HistEnt *htemp;
struct HistEnt *histent_head, *histent_tail;
char *parsed;
int len, i, j;
struct fac *f;

if(!(f=np->mv.mvlfac)) return;	/* already imported */

if(np->mv.mvlfac->flags&LT_SYM_F_ALIAS)
	{
	int alias = np->mv.mvlfac->node_alias;
	f=GLOBALS->mvlfacs_lxt_c_2+alias;

	if(GLOBALS->resolve_lxt_alias_to[alias])
		{
		if(!GLOBALS->resolve_lxt_alias_to[np->mv.mvlfac - GLOBALS->mvlfacs_lxt_c_2]) GLOBALS->resolve_lxt_alias_to[np->mv.mvlfac - GLOBALS->mvlfacs_lxt_c_2] = GLOBALS->resolve_lxt_alias_to[alias];
		}
		else
		{
		GLOBALS->resolve_lxt_alias_to[alias] = np;
		}

	while(f->flags&LT_SYM_F_ALIAS)
		{
		f=GLOBALS->mvlfacs_lxt_c_2+f->node_alias;

		if(GLOBALS->resolve_lxt_alias_to[f->node_alias])
			{
			if(!GLOBALS->resolve_lxt_alias_to[np->mv.mvlfac - GLOBALS->mvlfacs_lxt_c_2]) GLOBALS->resolve_lxt_alias_to[np->mv.mvlfac - GLOBALS->mvlfacs_lxt_c_2] = GLOBALS->resolve_lxt_alias_to[f->node_alias];
			}
			else
			{
			GLOBALS->resolve_lxt_alias_to[f->node_alias] = np;
			}
		}
	}

/* f is the head minus any aliases, np->mv.mvlfac is us... */
if(GLOBALS->resolve_lxt_alias_to[np->mv.mvlfac - GLOBALS->mvlfacs_lxt_c_2])	/* in case we're an alias head for later.. */
	{
	lxt_resolver(np, GLOBALS->resolve_lxt_alias_to[np->mv.mvlfac - GLOBALS->mvlfacs_lxt_c_2]);
	return;
	}

GLOBALS->resolve_lxt_alias_to[np->mv.mvlfac - GLOBALS->mvlfacs_lxt_c_2] = np;	/* in case we're an alias head for later.. */
offs=GLOBALS->lastchange[f-GLOBALS->mvlfacs_lxt_c_2];

tmval=LLDescriptor(-1);
prevtmval = LLDescriptor(-1);
len = np->mv.mvlfac->len;

histent_tail = htemp = histent_calloc();
if(len>1)
	{
	htemp->v.h_vector = (char *)malloc_2(len);
	for(i=0;i<len;i++) htemp->v.h_vector[i] = AN_Z;
	}
	else
	{
	htemp->v.h_val = AN_Z;		/* z */
	}
htemp->time = MAX_HISTENT_TIME;

histent_head = histent_calloc();
if(len>1)
	{
	histent_head->v.h_vector = (char *)malloc_2(len);
	for(i=0;i<len;i++) histent_head->v.h_vector[i] = AN_X;
	}
	else
	{
	histent_head->v.h_val = AN_X; /* x */
	}
histent_head->time = MAX_HISTENT_TIME-1;
histent_head->next = htemp;	/* x */

np->numhist=2;

if(f->node_alias < 1)	/* sorry, arrays not supported */
while(offs)
	{
	unsigned char val = 0;

	if( (w=((v=get_byte(offs))&0xF)) >0xb)
		{
		off_t offsminus1, offsminus2, offsminus3;
		TimeType delta, time_offsminus1;
		int skip;

		switch(v&0xF0)
			{
			case 0x00:
				skip = 2;
				offsdelta=get_byte(offs+1);
				break;
			case 0x10:
				skip = 3;
				offsdelta=get_16(offs+1);
				break;
			case 0x20:
				skip = 4;
				offsdelta=get_24(offs+1);
				break;
			case 0x30:
				skip = 5;
				offsdelta=get_32(offs+1);
				break;
			default:
				fprintf(stderr, "Unknown %02x at offset: %08x\n", v, (unsigned int)offs);
				exit(0);
			}
		offsminus1 = offs-offsdelta-2;

		switch(get_byte(offsminus1)&0xF0)
			{
			case 0x00:
				offsdelta=get_byte(offsminus1+1);
				break;
			case 0x10:
				offsdelta=get_16(offsminus1+1);
				break;
			case 0x20:
				offsdelta=get_24(offsminus1+1);
				break;
			case 0x30:
				offsdelta=get_32(offsminus1+1);
				break;
			default:
				fprintf(stderr, "Unknown %02x at offset: %08x\n", get_byte(offsminus1), (unsigned int)offsminus1);
				exit(0);
			}
		offsminus2 = offsminus1-offsdelta-2;

		delta = (time_offsminus1=bsearch_mvl_timechain(offsminus1)) - bsearch_mvl_timechain(offsminus2);

		if(len>1)
			{
			DEBUG(fprintf(stderr, "!!! DELTA = %lld\n", delta));
			DEBUG(fprintf(stderr, "!!! offsminus1 = %08x\n", offsminus1));

			if(!GLOBALS->lxt_clock_compress_to_z)
				{
				int vval = get_byte(offsminus1)&0xF;
				int reps = 0;
				int rcnt;
				unsigned int reconstructm1 = 0;
				unsigned int reconstructm2 = 0;
				unsigned int reconstructm3 = 0;
				unsigned int rle_delta[2];
				int ix;

				if((vval!=0)&&(vval!=3)&&(vval!=4))
					{
					fprintf(stderr, "Unexpected clk compress byte %02x at offset: %08x\n", get_byte(offsminus1), (unsigned int)offsminus1);
					exit(0);
					}

				switch(w&3)
					{
					case 0:	reps = get_byte(offs+skip); break;
					case 1: reps = get_16(offs+skip); break;
					case 2: reps = get_24(offs+skip); break;
					case 3: reps = get_32(offs+skip); break;
					}

				reps++;

				DEBUG(fprintf(stderr, "!!! reps = %d\n", reps));

				parsed=parse_offset(f, offsminus1);
				for(ix=0;ix<len;ix++)
					{
					reconstructm1 <<= 1;
					reconstructm1 |= (parsed[ix]&1);
					}

				DEBUG(fprintf(stderr, "!!! M1 = '%08x'\n", reconstructm1));

				parsed=parse_offset(f, offsminus2);
				for(ix=0;ix<len;ix++)
					{
					reconstructm2 <<= 1;
					reconstructm2 |= (parsed[ix]&1);
					}

				DEBUG(fprintf(stderr, "!!! M2 = '%08x'\n", reconstructm2));

				switch(get_byte(offsminus2)&0xF0)
					{
					case 0x00:
						offsdelta=get_byte(offsminus2+1);
						break;
					case 0x10:
						offsdelta=get_16(offsminus2+1);
						break;
					case 0x20:
						offsdelta=get_24(offsminus2+1);
						break;
					case 0x30:
						offsdelta=get_32(offsminus2+1);
						break;
					default:
						fprintf(stderr, "Unknown %02x at offset: %08x\n", get_byte(offsminus2), (unsigned int)offsminus2);
						exit(0);
					}
				offsminus3 = offsminus2-offsdelta-2;

				parsed=parse_offset(f, offsminus3);
				for(ix=0;ix<len;ix++)
					{
					reconstructm3 <<= 1;
					reconstructm3 |= (parsed[ix]&1);
					}

				DEBUG(fprintf(stderr, "!!! M3 = '%08x'\n", reconstructm3));

				rle_delta[0] = reconstructm2 - reconstructm3;
				rle_delta[1] = reconstructm1 - reconstructm2;

				DEBUG(fprintf(stderr, "!!! RLE0 = '%08x'\n", rle_delta[0]));
				DEBUG(fprintf(stderr, "!!! RLE1 = '%08x'\n", rle_delta[1]));

				DEBUG(fprintf(stderr, "!!! time_offsminus1 = %lld\n", time_offsminus1));

				tmval = time_offsminus1 + (delta * reps);
				for(rcnt=0;rcnt<reps;rcnt++)
					{
					int k;
					int jx = (reps - rcnt);
					unsigned int res = reconstructm1 +
						((jx/2)+(jx&0))*rle_delta[1] +
						((jx/2)+(jx&1))*rle_delta[0];

					DEBUG(fprintf(stderr, "!!! %lld -> '%08x'\n", tmval, res));

					for(k=0;k<len;k++)
						{
						parsed[k] = ((1<<(len-k-1)) & res) ? '1' : '0';
						}

					htemp = histent_calloc();
					htemp->v.h_vector = (char *)malloc_2(len);
					memcpy(htemp->v.h_vector, parsed, len);
					htemp->time = tmval;
					htemp->next = histent_head;
					histent_head = htemp;
					np->numhist++;

					tmval-=delta;
					}
				}
				else	/* compress to z on multibit */
				{
				int ix;

				htemp = histent_calloc();
				htemp->v.h_vector = (char *)malloc_2(len);
				for(ix=0;ix<len;ix++) { htemp->v.h_vector[ix] = 'z'; }
				tmval = time_offsminus1 + delta;
				htemp->time = tmval;
				htemp->next = histent_head;
				histent_head = htemp;
				np->numhist++;
				}

			offs = offsminus1;	/* no need to recalc it again! */
			continue;
			}
			else
			{
			if(!GLOBALS->lxt_clock_compress_to_z)
				{
				int vval = get_byte(offsminus1)&0xF;
				int reps = 0;
				int rcnt;

				if((vval<3)||(vval>4))
					{
					fprintf(stderr, "Unexpected clk compress byte %02x at offset: %08x\n", get_byte(offsminus1), (unsigned int)offsminus1);
					exit(0);
					}

				switch(w&3)
					{
					case 0:	reps = get_byte(offs+skip); break;
					case 1: reps = get_16(offs+skip); break;
					case 2: reps = get_24(offs+skip); break;
					case 3: reps = get_32(offs+skip); break;
					}

				reps++;
				vval = (reps & 1) ^ (vval==4);	/* because x3='0', x4='1' */
				vval = (vval==0) ? AN_0 : AN_1;

				tmval = time_offsminus1 + (delta * reps);
				for(rcnt=0;rcnt<reps;rcnt++)
					{
					if(vval!=histent_head->v.h_val)
						{
						htemp = histent_calloc();
						htemp->v.h_val = vval;
						htemp->time = tmval;
						htemp->next = histent_head;
						histent_head = htemp;
						np->numhist++;
						}
						else
						{
						histent_head->time = tmval;
						}

					tmval-=delta;
					vval= (vval==AN_0) ? AN_1: AN_0;
					}
				}
				else
				{
				int vval=AN_Z;

				if(vval!=histent_head->v.h_val)
					{
					htemp = histent_calloc();
					htemp->v.h_val = vval;
					htemp->time = time_offsminus1 + delta;
					htemp->next = histent_head;
					histent_head = htemp;
					np->numhist++;
					}
					else
					{
					histent_head->time = time_offsminus1 + delta;
					}
				tmval = time_offsminus1 + delta;
				}
			}

		offs = offsminus1;	/* no need to recalc it again! */
		continue;
		}
	else
	if((tmval=bsearch_mvl_timechain(offs))!=prevtmval)	/* get rid of glitches (if even possible) */
		{
		DEBUG(printf(LXTHDR"offs: %08x is time %08x\n", offs, tmval));
		if(!(f->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING)))
			{
			parsed=parse_offset(f, offs);

			if(len==1)
				{
				switch(parsed[0])
					{
				        case '0':       val = AN_0; break;
				        case 'x':	val = AN_X; break;
				        case 'z':	val = AN_Z; break;
				        case '1':       val = AN_1; break;
                                        case 'h':       val = AN_H; break;
                                        case 'u':       val = AN_U; break;
                                        case 'w':       val = AN_W; break;
                                        case 'l':       val = AN_L; break;
                                        case '-':       val = AN_DASH; break;
				        }

				if(val!=histent_head->v.h_val)
					{
					htemp = histent_calloc();
					htemp->v.h_val = val;
					htemp->time = tmval;
					htemp->next = histent_head;
					histent_head = htemp;
					np->numhist++;
					}
					else
					{
					histent_head->time = tmval;
					}
				}
				else
				{
				if(memcmp(parsed, histent_head->v.h_vector, len))
					{
					htemp = histent_calloc();
					htemp->v.h_vector = (char *)malloc_2(len);
					memcpy(htemp->v.h_vector, parsed, len);
					htemp->time = tmval;
					htemp->next = histent_head;
					histent_head = htemp;
					np->numhist++;
					}
					else
					{
					histent_head->time = tmval;
					}
				}
			}
		else
		if(f->flags&LT_SYM_F_DOUBLE)
			{
			int offs_dbl = offs + ((get_byte(offs)>>4)&3)+2;   /* skip value */

			htemp = histent_calloc();
			htemp->flags = HIST_REAL;

			if(GLOBALS->double_is_native_lxt_c_1)
				{
#ifdef WAVE_HAS_H_DOUBLE
				memcpy(&htemp->v.h_double, ((char *)GLOBALS->mm_lxt_c_1+offs_dbl), sizeof(double));
#else
				htemp->v.h_vector = ((char *)GLOBALS->mm_lxt_c_1+offs_dbl);
				DEBUG(printf(LXTHDR"Added double '%.16g'\n", *((double *)(GLOBALS->mm_lxt_c_1+offs_dbl))));
#endif
				}
				else
				{
#ifdef WAVE_HAS_H_DOUBLE
				double *h_d = (double *)swab_double_via_mask(offs_dbl);
				htemp->v.h_double = *h_d;
				free_2(h_d);
#else
				htemp->v.h_vector = swab_double_via_mask(offs_dbl);
				DEBUG(printf(LXTHDR"Added bytefixed double '%.16g'\n", *((double *)(htemp->v.h_vector))));
#endif
				}
			htemp->time = tmval;
			htemp->next = histent_head;
			histent_head = htemp;
			np->numhist++;
			}
			else
			{						/* defaults to if(f->flags&LT_SYM_F_STRING) */
			int offs_str = offs + ((get_byte(offs)>>4)&3)+2;   /* skip value */

			htemp = histent_calloc();
			htemp->flags = HIST_REAL|HIST_STRING;

			htemp->v.h_vector = ((char *)GLOBALS->mm_lxt_c_1+offs_str);
			DEBUG(printf(LXTHDR"Added string '%s'\n", (unsigned char *)GLOBALS->mm_lxt_c_1+offs_str));
			htemp->time = tmval;
			htemp->next = histent_head;
			histent_head = htemp;
			np->numhist++;
			}
		}

	prevtmval = tmval;

/*	v=get_byte(offs); */
	switch(v&0xF0)
		{
		case 0x00:
			offsdelta=get_byte(offs+1);
			break;

		case 0x10:
			offsdelta=get_16(offs+1);
			break;

		case 0x20:
			offsdelta=get_24(offs+1);
			break;

		case 0x30:
			offsdelta=get_32(offs+1);
			break;

		default:
			fprintf(stderr, "Unknown %02x at offset: %08x\n", v, (unsigned int)offs);
			exit(0);
		}

	offs = offs-offsdelta-2;
	}

np->mv.mvlfac = NULL;	/* it's imported and cached so we can forget it's an mvlfac now */

for(j=0;j>-2;j--)
	{
	if(tmval!=GLOBALS->first_cycle_lxt_c_2)
		{
		char init;

		htemp = histent_calloc();

		if(!(f->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING)))
			{
			if(GLOBALS->initial_value_offset_lxt_c_1)
				{
				init = GLOBALS->initial_value_lxt_c_1;
				}
				else
				{
				init = AN_X; /* x if unspecified */
				}

			if(len>1)
				{
				char *pnt = htemp->v.h_vector = (char *)malloc_2(len);	/* zeros */
				int ix;
				for(ix=0;ix<len;ix++)
					{
					*(pnt++) = init;
					}
				}
				else
				{
				htemp->v.h_val = init;
				}
			}
			else
			{
			htemp->flags = HIST_REAL;
			if(f->flags&LT_SYM_F_STRING) htemp->flags |= HIST_STRING;
			}

		htemp->time = GLOBALS->first_cycle_lxt_c_2+j;
		htemp->next = histent_head;
		histent_head = htemp;
		np->numhist++;
		}

	tmval=GLOBALS->first_cycle_lxt_c_2+1;
	}

if(!(f->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING)))
	{
	if(len>1)
		{
		np->head.v.h_vector = (char *)malloc_2(len);
		for(i=0;i<len;i++) np->head.v.h_vector[i] = AN_X;
		}
		else
		{
		np->head.v.h_val = AN_X;                     /* 'x' */
		}
	}
	else
	{
	np->head.flags = HIST_REAL;
	if(f->flags&LT_SYM_F_STRING) np->head.flags |= HIST_STRING;
	}
np->head.time  = -2;
np->head.next = histent_head;
np->curr = histent_tail;
np->numhist++;
}

