/*
 * Copyright (c) Tony Bybell 1999-2017.
 *
 * 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 "globals.h"
#include <config.h>
#include <math.h>
#include <string.h>
#include "gtk23compat.h"
#include "currenttime.h"
#include "pixmaps.h"
#include "symbol.h"
#include "bsearch.h"
#include "color.h"
#include "strace.h"
#include "debug.h"
#include "translate.h"
#include "ptranslate.h"
#include "ttranslate.h"
#include "pipeio.h"

/*
 * filters mutually exclusive with file/translate/process filters
 */
static char *lzremoval(char *s)
{
char *p = s;

if(*p)
	{
	while((*p=='0') && *(p+1))
		{
		p++;
		}
	}

if(p != s)
	{
	memmove(s, p, strlen(p) + 1);
	}

return(s);
}

/*
 * file/translate/process filters
 */
static char *dofilter(Trptr t, char *s)
{
GLOBALS->xl_file_filter[t->f_filter] = xl_splay(s, GLOBALS->xl_file_filter[t->f_filter]);

if(!strcasecmp(s, GLOBALS->xl_file_filter[t->f_filter]->item))
	{
	free_2(s);
	s = malloc_2(strlen(GLOBALS->xl_file_filter[t->f_filter]->trans) + 1);
	strcpy(s, GLOBALS->xl_file_filter[t->f_filter]->trans);
	}

if((*s == '?') && (!GLOBALS->color_active_in_filter))
	{
	char *s2a;
	char *s2 = strchr(s+1, '?');
	if(s2)
		{
		s2++;
		s2a = malloc_2(strlen(s2)+1);
		strcpy(s2a, s2);
		free_2(s);
		s = s2a;
		}
	}

return(s);
}

static char *edofilter(Trptr t, char *s)
{
if(t->flags & TR_ENUM)
	{
	int filt = t->e_filter - 1;

#ifdef _WAVE_HAVE_JUDY
	PPvoid_t pv = JudyHSGet(GLOBALS->xl_enum_filter[filt], s, strlen(s));
	if(pv)
		{
		free_2(s);
		s = malloc_2(strlen(*pv) + 1);
		strcpy(s, *pv);
		}
#else
	GLOBALS->xl_enum_filter[filt] = xl_splay(s, GLOBALS->xl_enum_filter[filt]);

	if(!strcasecmp(s, GLOBALS->xl_enum_filter[filt]->item))
		{
		free_2(s);
		s = malloc_2(strlen(GLOBALS->xl_enum_filter[filt]->trans) + 1);
		strcpy(s, GLOBALS->xl_enum_filter[filt]->trans);
		}
#endif
	else
		{
		char *zerofind = s;
		char *dst = s, *src;
		while(*zerofind == '0') zerofind++;
		if(zerofind != s)
			{
			src = (!*zerofind) ? (zerofind-1) : zerofind;
			while(*src)
				{
				*(dst++) = *(src++);
				}
			*dst = 0;
			}
		}
	}

return(s);
}

static char *pdofilter(Trptr t, char *s)
{
struct pipe_ctx *p = GLOBALS->proc_filter[t->p_filter];
char buf[1025];
int n;

if(p)
	{
#if !defined __MINGW32__
	fputs(s, p->sout);
	fputc('\n', p->sout);
	fflush(p->sout);

	buf[0] = 0;

	n = fgets(buf, 1024, p->sin) ? strlen(buf) : 0;
	buf[n] = 0;
#else
	{
	BOOL bSuccess;
	DWORD dwWritten, dwRead;

	WriteFile(p->g_hChildStd_IN_Wr, s, strlen(s), &dwWritten, NULL);
	WriteFile(p->g_hChildStd_IN_Wr, "\n", 1, &dwWritten, NULL);

	for(n=0;n<1024;n++)
		{
		do 	{
			bSuccess = ReadFile(p->g_hChildStd_OUT_Rd, buf+n, 1, &dwRead, NULL);
			if((!bSuccess)||(buf[n]=='\n'))
				{
				goto ex;
				}

			} while(buf[n]=='\r');
		}
ex:	buf[n] = 0;
	}

#endif

	if(n)
		{
		if(buf[n-1] == '\n') { buf[n-1] = 0; n--; }
		}

	if(buf[0])
		{
		free_2(s);
		s = malloc_2(n + 1);
		strcpy(s, buf);
		}
	}

if((*s == '?') && (!GLOBALS->color_active_in_filter))
	{
	char *s2a;
	char *s2 = strchr(s+1, '?');
	if(s2)
		{
		s2++;
		s2a = malloc_2(strlen(s2)+1);
		strcpy(s2a, s2);
		free_2(s);
		s = s2a;
		}
	}
return(s);
}


/*
 * convert binary <=> gray/ffo/popcnt in place
 */
#define cvt_gray(f,p,n) \
do { \
if((f)&(TR_GRAYMASK|TR_POPCNT|TR_FFO)) \
	{ \
	if((f)&TR_BINGRAY) { convert_bingray((p),(n)); } \
	if((f)&TR_GRAYBIN) { convert_graybin((p),(n)); } \
	if((f)&TR_FFO)     { convert_ffo((p),(n)); } \
	if((f)&TR_POPCNT)  { convert_popcnt((p),(n)); } \
	} \
} while(0)


static void convert_graybin(char *pnt, int nbits)
{
char kill_state = 0;
char pch = AN_0;
int i;

for(i=0;i<nbits;i++)
	{
	char ch = pnt[i];

	if(!kill_state)
		{
		switch(ch)
			{
			case AN_0:
			case AN_L:
					if((pch == AN_1) || (pch == AN_H))
						{
						pnt[i] = pch;
						}
					break;

			case AN_1:
			case AN_H:
					if(pch == AN_1)
						{
						pnt[i] = AN_0;
						}
					else if(pch == AN_H)
						{
						pnt[i] = AN_L;
						}
					break;

			default:
					kill_state = 1;
					break;
			}

		pch = pnt[i];	/* pch is xor accumulator */
		}
		else
		{
		pnt[i] = pch;
		}
	}
}

static void convert_bingray(char *pnt, int nbits)
{
char kill_state = 0;
char pch = AN_0;
int i;

for(i=0;i<nbits;i++)
	{
	char ch = pnt[i];

	if(!kill_state)
		{
		switch(ch)
			{
			case AN_0:
			case AN_L:
					if((pch == AN_1) || (pch == AN_H))
						{
						pnt[i] = pch;
						}
					break;

			case AN_1:
			case AN_H:
					if(pch == AN_1)
						{
						pnt[i] = AN_0;
						}
					else if(pch == AN_H)
						{
						pnt[i] = AN_L;
						}
					break;

			default:
					kill_state = 1;
					break;
			}

		pch = ch;	/* pch is previous character */
		}
		else
		{
		pnt[i] = pch;
		}
	}
}


static void convert_popcnt(char *pnt, int nbits)
{
int i;
unsigned int pop = 0;

for(i=0;i<nbits;i++)
	{
	char ch = pnt[i];

	switch(ch)
		{
		case AN_1:
		case AN_H:	pop++;
				break;

		default:
				break;
			}

	}

for(i=nbits-1;i>=0;i--) /* always requires less number of bits */
	{
	pnt[i] = (pop & 1) ? AN_1 : AN_0;
	pop >>= 1;
	}
}


static void convert_ffo(char *pnt, int nbits)
{
int i;
int ffo = -1;

for(i=(nbits-1);i>=0;i--)
	{
	char ch = pnt[i];

	if((ch == AN_1) || (ch == AN_H))
		{
		ffo = (nbits-1) - i;
		break;
		}
	}

if(ffo >= 0)
	{
	for(i=nbits-1;i>=0;i--) /* always requires less number of bits */
		{
		pnt[i] = (ffo & 1) ? AN_1 : AN_0;
		ffo >>= 1;
		}
	}
	else
	{
	for(i=nbits-1;i>=0;i--) /* always requires less number of bits */
		{
		pnt[i] = AN_X;
		}
	}
}


static void dpr_e16(char *str, double d)
{
char *buf16;
char buf15[24];
int l16;
int l15;

buf16 = str;
buf16[23] = 0;
l16 = snprintf(buf16, 24, "%.16g", d);
if(l16 >= 18)
        {
        buf15[23] = 0;
        l15 = snprintf(buf15, 24, "%.15g", d);
        if((l16-l15) > 3)
                {
                strcpy(str, buf15);
                }
        }
}


static void cvt_fpsdec(Trptr t, TimeType val, char *os, int len, int nbits)
{
(void)nbits; /* number of bits shouldn't be relevant here as we're going through a fraction */

int shamt = t->t_fpdecshift;
TimeType lpart = val >> shamt;
TimeType rmsk = (ULLDescriptor(1) << shamt);
TimeType rbit = (val >= 0) ? (val & (rmsk-1)) : ((-val) & (rmsk-1));
double rfrac;
int negflag = 0;
char dbuf[32];
char bigbuf[64];


if(rmsk)
        {
        rfrac = (double)rbit / (double)rmsk;

        if(shamt)
                {
                if(lpart < 0)
                        {
                        if(rbit)
                                {
                                lpart++;
                                if(!lpart) negflag = 1;
                                }
                        }
                }

        }
        else
        {
        rfrac = 0.0;
        }

dpr_e16(dbuf, rfrac); /* sprintf(dbuf, "%.16g", rfrac); */
char *dot = strchr(dbuf, '.');

if(dot && (dbuf[0] == '0'))
        {
	sprintf(bigbuf, "%s"TTFormat".%s", negflag ? "-" : "", lpart, dot+1);
        strncpy(os, bigbuf, len);
        os[len-1] = 0;
        }
        else
        {
	sprintf(os, "%s"TTFormat, negflag ? "-" : "", lpart);
        }
}

static void cvt_fpsudec(Trptr t, TimeType val, char *os, int len)
{
int shamt = t->t_fpdecshift;
UTimeType lpart = ((UTimeType)val) >> shamt;
TimeType rmsk = (ULLDescriptor(1) << shamt);
TimeType rbit = (val & (rmsk-1));
double rfrac;
char dbuf[32];
char bigbuf[64];

if(rmsk)
	{
	rfrac = (double)rbit / (double)rmsk;
	}
	else
	{
	rfrac = 0.0;
	}			

dpr_e16(dbuf, rfrac); /* sprintf(dbuf, "%.16g", rfrac);	*/
char *dot = strchr(dbuf, '.');
if(dot && (dbuf[0] == '0'))
	{
	sprintf(bigbuf, UTTFormat".%s", lpart, dot+1);
	strncpy(os, bigbuf, len);
	os[len-1] = 0;
	}
	else
	{
	sprintf(os, UTTFormat, lpart);
	}
}


/*
 * convert trptr+vptr into an ascii string
 */
static char *convert_ascii_2(Trptr t, vptr v)
{
TraceFlagsType flags;
int nbits;
unsigned char *bits;
char *os, *pnt, *newbuff;
int i, j, len;

static const char xfwd[AN_COUNT]= AN_NORMAL  ;
static const char xrev[AN_COUNT]= AN_INVERSE ;
const char *xtab;

flags=t->flags;
nbits=t->n.vec->nbits;
bits=v->v;

if(flags&TR_INVERT)
	{
	xtab = xrev;
	}
	else
	{
	xtab = xfwd;
	}

if(flags&(TR_ZEROFILL|TR_ONEFILL))
	{
	char whichfill = (flags&TR_ZEROFILL) ? AN_0 : AN_1;
	int msi = 0, lsi = 0, ok = 0;
	if((t->name)&&(nbits > 1))
		{
		char *lbrack = strrchr(t->name, '[');
		if(lbrack)
			{
			int rc = sscanf(lbrack+1, "%d:%d", &msi, &lsi);
			if(rc == 2)
				{
				if(((msi - lsi + 1) == nbits) || ((lsi - msi + 1) == nbits))
					{
					ok = 1;	/* to ensure sanity... */
					}
				}
			}
		}

	if(ok)
		{
		if(msi > lsi)
			{
			if(lsi > 0)
				{
				pnt=wave_alloca(msi + 1);

				memcpy(pnt, bits, nbits);

	        		for(i=nbits;i<msi+1;i++)
	                		{
	                		pnt[i]=whichfill;
	                		}

				bits = (unsigned char *)pnt;
				nbits = msi + 1;
				}
			}
			else
			{
			if(msi > 0)
				{
				pnt=wave_alloca(lsi + 1);

	        		for(i=0;i<msi;i++)
	                		{
	                		pnt[i]=whichfill;
	                		}

				memcpy(pnt+i, bits, nbits);

				bits = (unsigned char *)pnt;
				nbits = lsi + 1;
				}
			}
		}
	}


newbuff=(char *)malloc_2(nbits+6); /* for justify */
if(flags&TR_REVERSE)
	{
	char *fwdpnt, *revpnt;

	fwdpnt=(char *)bits;
	revpnt=newbuff+nbits+6;
	/* for(i=0;i<3;i++) *(--revpnt)=xtab[0]; */
	for(i=0;i<3;i++) *(--revpnt)=xfwd[0];
	for(i=0;i<nbits;i++)
		{
		*(--revpnt)=xtab[(int)(*(fwdpnt++))];
		}
	/* for(i=0;i<3;i++) *(--revpnt)=xtab[0]; */
	for(i=0;i<3;i++) *(--revpnt)=xfwd[0];
	}
	else
	{
	char *fwdpnt, *fwdpnt2;

	fwdpnt=(char *)bits;
	fwdpnt2=newbuff;
	/* for(i=0;i<3;i++) *(fwdpnt2++)=xtab[0]; */
	for(i=0;i<3;i++) *(fwdpnt2++)=xfwd[0];
	for(i=0;i<nbits;i++)
		{
		*(fwdpnt2++)=xtab[(int)(*(fwdpnt++))];
		}
	/* for(i=0;i<3;i++) *(fwdpnt2++)=xtab[0]; */
	for(i=0;i<3;i++) *(fwdpnt2++)=xfwd[0];
	}


if(flags&TR_ASCII)
	{
	char *parse;
	int found=0;

	free_2(newbuff);
	newbuff=(char *)malloc_2(nbits+14); /* for justify */
	if(flags&TR_REVERSE)
		{
		char *fwdpnt, *revpnt;
	
		fwdpnt=(char *)bits;
		revpnt=newbuff+nbits+14;
		for(i=0;i<7;i++) *(--revpnt)=xfwd[0];
		for(i=0;i<nbits;i++)
			{
			*(--revpnt)=xtab[(int)(*(fwdpnt++))];
			}
		for(i=0;i<7;i++) *(--revpnt)=xfwd[0];
		}
		else
		{
		char *fwdpnt, *fwdpnt2;
	
		fwdpnt=(char *)bits;
		fwdpnt2=newbuff;
		for(i=0;i<7;i++) *(fwdpnt2++)=xfwd[0];
		for(i=0;i<nbits;i++)
			{
			*(fwdpnt2++)=xtab[(int)(*(fwdpnt++))];
			}
		for(i=0;i<7;i++) *(fwdpnt2++)=xfwd[0];
		}

	len=(nbits/8)+2+2;		/* $xxxxx */
	os=pnt=(char *)calloc_2(1,len);
	if(GLOBALS->show_base) { *(pnt++)='"'; }

	parse=(flags&TR_RJUSTIFY)?(newbuff+((nbits+7)&7)):(newbuff+7);
	cvt_gray(flags,parse,(flags&TR_RJUSTIFY)?((nbits+7)&~7):nbits);

	for(i=0;i<nbits;i+=8)
		{
		unsigned long val;

		val=0;
		for(j=0;j<8;j++)
			{
			val<<=1;

			if((parse[j]==AN_X)||(parse[j]==AN_Z)||(parse[j]==AN_W)||(parse[j]==AN_U)||(parse[j]==AN_DASH)) { val=1000; /* arbitrarily large */}
			if((parse[j]==AN_1)||(parse[j]==AN_H)) { val|=1; }
			}


		if (val) {
			if (val > 0x7f || !isprint(val)) *pnt++ = '.'; else *pnt++ = val;
			found=1;
		}

		parse+=8;
		}
	if (!found && !GLOBALS->show_base) {
		*(pnt++)='"';
		*(pnt++)='"';
	}

	if(GLOBALS->show_base) { *(pnt++)='"'; }
	*(pnt)=0x00; /* scan build : remove dead increment */
	}
else if((flags&TR_HEX)||((flags&(TR_DEC|TR_SIGNED))&&(nbits>64)&&(!(flags&(TR_POPCNT|TR_FFO)))))
	{
	char *parse;

	len=(nbits/4)+2+1;		/* $xxxxx */
	os=pnt=(char *)calloc_2(1,len);
	if(GLOBALS->show_base) { *(pnt++)='$'; }

	parse=(flags&TR_RJUSTIFY)?(newbuff+((nbits+3)&3)):(newbuff+3);
	cvt_gray(flags,parse,(flags&TR_RJUSTIFY)?((nbits+3)&~3):nbits);

	for(i=0;i<nbits;i+=4)
		{
		unsigned char val;

		val=0;
		for(j=0;j<4;j++)
			{
			val<<=1;

			if((parse[j]==AN_1)||(parse[j]==AN_H))
				{
				val|=1;
				}
			else
			if((parse[j]==AN_0)||(parse[j]==AN_L))
				{
				}
			else
			if(parse[j]==AN_X)
				{
				int match = (j==0) || ((parse + i + j) == (newbuff + 3));
				int k;
				for(k=j+1;k<4;k++)
					{
					if(parse[k]!=AN_X)
						{
						char *thisbyt = parse + i + k;
						char *lastbyt = newbuff + 3 + nbits - 1;
						if((lastbyt - thisbyt) >= 0) match = 0;
						break;
						}
					}
				val = (match) ? 16 : 21; break;
				}
			else
			if(parse[j]==AN_Z)
				{
				int xover = 0;
				int match = (j==0) || ((parse + i + j) == (newbuff + 3));
				int k;
				for(k=j+1;k<4;k++)
					{
					if(parse[k]!=AN_Z)
						{
						if(parse[k]==AN_X)
							{
							xover = 1;
							}
							else
							{
							char *thisbyt = parse + i + k;
							char *lastbyt = newbuff + 3 + nbits - 1;
							if((lastbyt - thisbyt) >= 0) match = 0;
							}
						break;
						}
					}

				if(xover) val = 21;
				else val = (match) ? 17 : 22;
				break;
				}
			else
			if(parse[j]==AN_W)
				{
				int xover = 0;
				int match = (j==0) || ((parse + i + j) == (newbuff + 3));
				int k;
				for(k=j+1;k<4;k++)
					{
					if(parse[k]!=AN_W)
						{
						if(parse[k]==AN_X)
							{
							xover = 1;
							}
							else
							{
							char *thisbyt = parse + i + k;
							char *lastbyt = newbuff + 3 + nbits - 1;
							if((lastbyt - thisbyt) >= 0) match = 0;
							}
						break;
						}
					}

				if(xover) val = 21;
				else val = (match) ? 18 : 23;
				break;
				}
			else
			if(parse[j]==AN_U)
				{
				int xover = 0;
				int match = (j==0) || ((parse + i + j) == (newbuff + 3));
				int k;
				for(k=j+1;k<4;k++)
					{
					if(parse[k]!=AN_U)
						{
						if(parse[k]==AN_X)
							{
							xover = 1;
							}
							else
							{
							char *thisbyt = parse + i + k;
							char *lastbyt = newbuff + 3 + nbits - 1;
							if((lastbyt - thisbyt) >= 0) match = 0;
							}
						break;
						}
					}

				if(xover) val = 21;
				else val = (match) ? 19 : 24;
				break;
				}
			else
			if(parse[j]==AN_DASH)
				{
				int xover = 0;
				int k;
				for(k=j+1;k<4;k++)
					{
					if(parse[k]!=AN_DASH)
						{
						if(parse[k]==AN_X)
							{
							xover = 1;
							}
						break;
						}
					}

				if(xover) val = 21;
				else val = 20;
				break;
				}
			}

		*(pnt++)=AN_HEX_STR[val];

		parse+=4;
		}

	*(pnt)=0x00;  /* scan build : remove dead increment */
	}
else if(flags&TR_OCT)
	{
	char *parse;

	len=(nbits/3)+2+1;		/* #xxxxx */
	os=pnt=(char *)calloc_2(1,len);
	if(GLOBALS->show_base) { *(pnt++)='#'; }

	parse=(flags&TR_RJUSTIFY)
		?(newbuff+((nbits%3)?(nbits%3):3))
		:(newbuff+3);
	cvt_gray(flags,parse,(flags&TR_RJUSTIFY)?(((nbits+2)/3)*3):nbits);

	for(i=0;i<nbits;i+=3)
		{
		unsigned char val;

		val=0;
		for(j=0;j<3;j++)
			{
			val<<=1;

			if(parse[j]==AN_X) { val=8; break; }
			if(parse[j]==AN_Z) { val=9; break; }
			if(parse[j]==AN_W) { val=10; break; }
			if(parse[j]==AN_U) { val=11; break; }
			if(parse[j]==AN_DASH) { val=12; break; }

			if((parse[j]==AN_1)||(parse[j]==AN_H)) { val|=1; }
			}

		*(pnt++)=AN_OCT_STR[val];

		parse+=3;
		}

	*(pnt)=0x00; /* scan build : remove dead increment */
	}
else if(flags&TR_BIN)
	{
	char *parse;

	len=(nbits/1)+2+1;		/* %xxxxx */
	os=pnt=(char *)calloc_2(1,len);
	if(GLOBALS->show_base) { *(pnt++)='%'; }

	parse=newbuff+3;
	cvt_gray(flags,parse,nbits);

	for(i=0;i<nbits;i++)
		{
		*(pnt++)=AN_STR[(int)(*(parse++))];
		}

	*(pnt)=0x00; /* scan build : remove dead increment */
	}
else if(flags&TR_SIGNED)
	{
	char *parse;
	TimeType val = 0;
	unsigned char fail=0;

	len=21;	/* len+1 of 0x8000000000000000 expressed in decimal */
	os=(char *)calloc_2(1,len);

	parse=newbuff+3;
	cvt_gray(flags,parse,nbits);

	if((parse[0]==AN_1)||(parse[0]==AN_H))
		{ val = LLDescriptor(-1); }
	else
	if((parse[0]==AN_0)||(parse[0]==AN_L))
		{ val = LLDescriptor(0); }
	else
		{ fail = 1; }

	if(!fail)
	for(i=1;i<nbits;i++)
		{
		val<<=1;

		if((parse[i]==AN_1)||(parse[i]==AN_H)) {  val|=LLDescriptor(1); }
		else if((parse[i]!=AN_0)&&(parse[i]!=AN_L)) { fail=1; break; }
		}

	if(!fail)
		{
		if((flags&TR_FPDECSHIFT)&&(t->t_fpdecshift))
			{
			cvt_fpsdec(t, val, os, len, nbits);
			}
			else
			{
                        if(!(flags&TR_TIME))
                                {
                                sprintf(os, TTFormat, val);
                                }
                                else
                                {
                                free_2(os);
                                os = calloc_2(1, 128);
                                reformat_time(os, val, GLOBALS->time_dimension);
                                }
			}
		}
		else
		{
		strcpy(os, "XXX");
		}
	}
else if(flags&TR_REAL)
	{
	char *parse;

	if((nbits==64) || (nbits==32))
		{
		UTimeType utt = LLDescriptor(0);
		double d;
		float f;
		uint32_t utt_32;

		parse=newbuff+3;
		cvt_gray(flags,parse,nbits);

		for(i=0;i<nbits;i++)
			{
			char ch = AN_STR[(int)(*(parse++))];
			if ((ch=='0')||(ch=='1'))
				{
				utt <<= 1;
				if(ch=='1')
					{
					utt |= LLDescriptor(1);
					}
				}
				else
				{
				goto rl_go_binary;
				}
			}

		os=/*pnt=*/(char *)calloc_2(1,64); /* scan-build */
		if(nbits==64)
			{
			memcpy(&d, &utt, sizeof(double));
		dpr_e16(os, d); /* sprintf(os, "%.16g", d); */
		}
		else
		{
			utt_32 = utt;
			memcpy(&f, &utt_32, sizeof(float));
			sprintf(os, "%f", f);
			}
		}
		else
		{
rl_go_binary:	len=(nbits/1)+2+1;		/* %xxxxx */
		os=pnt=(char *)calloc_2(1,len);
		if(GLOBALS->show_base) { *(pnt++)='%'; }

		parse=newbuff+3;
		cvt_gray(flags,parse,nbits);

		for(i=0;i<nbits;i++)
			{
			*(pnt++)=AN_STR[(int)(*(parse++))];
			}

		*(pnt)=0x00; /* scan build : remove dead increment */
		}
	}
else	/* decimal when all else fails */
	{
	char *parse;
	UTimeType val=0;
	unsigned char fail=0;

	len=21;	/* len+1 of 0xffffffffffffffff expressed in decimal */
	os=(char *)calloc_2(1,len);

	parse=newbuff+3;
	cvt_gray(flags,parse,nbits);

	for(i=0;i<nbits;i++)
		{
		val<<=1;

		if((parse[i]==AN_1)||(parse[i]==AN_H)) {  val|=LLDescriptor(1); }
		else if((parse[i]!=AN_0)&&(parse[i]!=AN_L)) { fail=1; break; }
		}

	if(!fail)
		{
		if((flags&TR_FPDECSHIFT)&&(t->t_fpdecshift))
			{
			cvt_fpsudec(t, val, os, len);
			}
			else
			{
                        if(!(flags&TR_TIME))
                                {
                                sprintf(os, UTTFormat, val);
                                }
                                else
                                {
                                free_2(os);
                                os = calloc_2(1, 128);
                                reformat_time(os, val, GLOBALS->time_dimension);
                                }
			}
		}
		else
		{
		strcpy(os, "XXX");
		}
	}

free_2(newbuff);
return(os);
}


/*
 * convert trptr+hptr vectorstring into an ascii string
 */
char *convert_ascii_real(Trptr t, double *d)
{
char *rv;

if(t && (t->flags & TR_REAL2BITS) && d) /* "real2bits" also allows other filters such as "bits2real" on top of it */
        {
	struct TraceEnt t2;
	char vec[64];
	int i;
	guint64 swapmem;

	memcpy(&swapmem, d, sizeof(guint64));
	for(i=0;i<64;i++)
		{
		if(swapmem & (ULLDescriptor(1)<<(63-i)))
			{
			vec[i] = AN_1;
			}
			else
			{
			vec[i] = AN_0;
			}
		}

	memcpy(&t2, t, sizeof(struct TraceEnt));

	t2.n.nd->msi = 63;
	t2.n.nd->lsi = 0;
	t2.flags &= ~(TR_REAL2BITS); /* to avoid possible recursion in the future */

	rv = convert_ascii_vec_2(&t2, vec);
        }
	else
	{
	rv=malloc_2(24);	/* enough for .16e format */

	if(d)
		{
		dpr_e16(rv, *d); /* sprintf(rv,"%.16g",*d); */
		}
	else
		{
		strcpy(rv,"UNDEF");
		}
	}

if(t)
	{
	if(!(t->f_filter|t->p_filter|t->e_filter))
	        {
		if(GLOBALS->lz_removal) lzremoval(rv);
	        }
	        else
	        {
	        if(t->e_filter)
	                {
	                rv = edofilter(t, rv);
	                }
	        else
	        if(t->f_filter)
	                {
	                rv = dofilter(t, rv);
	                }
	                else
	                {
	                rv = pdofilter(t, rv);
	                }
	        }
	}

return(rv);
}

char *convert_ascii_string(char *s)
{
char *rv;

if(s)
	{
	rv=(char *)malloc_2(strlen(s)+1);
	strcpy(rv, s);
	}
	else
	{
	rv=(char *)malloc_2(6);
	strcpy(rv, "UNDEF");
	}
return(rv);
}

static const unsigned char cvt_table[] = {
AN_0    /* . */, AN_X    /* . */, AN_Z    /* . */, AN_1    /* . */, AN_H    /* . */, AN_U    /* . */, AN_W    /* . */, AN_L    /* . */,
AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */,
AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */,
AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */,
AN_DASH /*   */, AN_DASH /* ! */, AN_DASH /* " */, AN_DASH /* # */, AN_DASH /* $ */, AN_DASH /* % */, AN_DASH /* & */, AN_DASH /* ' */,
AN_DASH /* ( */, AN_DASH /* ) */, AN_DASH /* * */, AN_DASH /* + */, AN_DASH /* , */, AN_DASH /* - */, AN_DASH /* . */, AN_DASH /* / */,
AN_0    /* 0 */, AN_1    /* 1 */, AN_DASH /* 2 */, AN_DASH /* 3 */, AN_DASH /* 4 */, AN_DASH /* 5 */, AN_DASH /* 6 */, AN_DASH /* 7 */,
AN_DASH /* 8 */, AN_DASH /* 9 */, AN_DASH /* : */, AN_DASH /* ; */, AN_DASH /* < */, AN_DASH /* = */, AN_DASH /* > */, AN_DASH /* ? */,
AN_DASH /* @ */, AN_DASH /* A */, AN_DASH /* B */, AN_DASH /* C */, AN_DASH /* D */, AN_DASH /* E */, AN_DASH /* F */, AN_DASH /* G */,
AN_H    /* H */, AN_DASH /* I */, AN_DASH /* J */, AN_DASH /* K */, AN_L    /* L */, AN_DASH /* M */, AN_DASH /* N */, AN_DASH /* O */,
AN_DASH /* P */, AN_DASH /* Q */, AN_DASH /* R */, AN_DASH /* S */, AN_DASH /* T */, AN_U    /* U */, AN_DASH /* V */, AN_W    /* W */,
AN_X    /* X */, AN_DASH /* Y */, AN_Z    /* Z */, AN_DASH /* [ */, AN_DASH /* \ */, AN_DASH /* ] */, AN_DASH /* ^ */, AN_DASH /* _ */,
AN_DASH /* ` */, AN_DASH /* a */, AN_DASH /* b */, AN_DASH /* c */, AN_DASH /* d */, AN_DASH /* e */, AN_DASH /* f */, AN_DASH /* g */,
AN_H    /* h */, AN_DASH /* i */, AN_DASH /* j */, AN_DASH /* k */, AN_L    /* l */, AN_DASH /* m */, AN_DASH /* n */, AN_DASH /* o */,
AN_DASH /* p */, AN_DASH /* q */, AN_DASH /* r */, AN_DASH /* s */, AN_DASH /* t */, AN_U    /* u */, AN_DASH /* v */, AN_W    /* w */,
AN_X    /* x */, AN_DASH /* y */, AN_Z    /* z */, AN_DASH /* { */, AN_DASH /* | */, AN_DASH /* } */, AN_DASH /* ~ */, AN_DASH /* . */,
AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */,
AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */,
AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */,
AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */,
AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */,
AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */,
AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */,
AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */,
AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */,
AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */,
AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */,
AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */,
AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */,
AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */,
AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */,
AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */, AN_DASH /* . */
};

int vtype(Trptr t, char *vec)
{
int i, nbits;
char pch, ch;

if (vec == NULL)
	return(AN_X);

nbits=t->n.nd->msi-t->n.nd->lsi;
if(nbits<0)nbits=-nbits;
nbits++;
pch = ch = cvt_table[(unsigned char)vec[0]];
for (i = 1; i < nbits; i++)
	{
	ch = cvt_table[(unsigned char)vec[i]];
        if(ch != pch) goto miscompare;
	}

return(ch);

miscompare:
if((pch == AN_X) || (pch == AN_U)) return(pch);
if(pch == AN_Z) return(AN_X);
for (; i < nbits; i++)
        {
	ch = cvt_table[(unsigned char)vec[i]];
        if((ch == AN_X) || (ch == AN_U)) return(ch);
        if(ch == AN_Z) return(AN_X);
	}

return(AN_COUNT);
}

int vtype2(Trptr t, vptr v)
{
int i, nbits;
char pch, ch;
char *vec=(char *)v->v;

if(!t->t_filter_converted)
	{
	if (vec == NULL)
		return(AN_X);
	}
	else
	{
	return ( ((vec == NULL) || (vec[0] == 0)) ? AN_Z : AN_COUNT );
	}

nbits=t->n.vec->nbits;

pch = ch = cvt_table[(unsigned char)vec[0]];
for (i = 1; i < nbits; i++)
		{
		ch = cvt_table[(unsigned char)vec[i]];
	        if(ch != pch) goto miscompare;
		}

return(ch);

miscompare:
if((pch == AN_X) || (pch == AN_U)) return(pch);
if(pch == AN_Z) return(AN_X);
for (; i < nbits; i++)
        {
	ch = cvt_table[(unsigned char)vec[i]];
        if((ch == AN_X) || (ch == AN_U)) return(ch);
        if(ch == AN_Z) return(AN_X);
	}

return(AN_COUNT);
}

/*
 * convert trptr+hptr vectorstring into an ascii string
 */
char *convert_ascii_vec_2(Trptr t, char *vec)
{
TraceFlagsType flags;
int nbits;
char *bits;
char *os, *pnt, *newbuff;
int i, j, len;
const char *xtab;

static const char xfwd[AN_COUNT]= AN_NORMAL  ;
static const char xrev[AN_COUNT]= AN_INVERSE ;

flags=t->flags;

nbits=t->n.nd->msi-t->n.nd->lsi;
if(nbits<0)nbits=-nbits;
nbits++;

if(vec)
        {
        bits=vec;
        if(*vec>AN_MSK)              /* convert as needed */
        for(i=0;i<nbits;i++)
                {
		vec[i] = cvt_table[(unsigned char)vec[i]];
                }
        }
        else
        {
        pnt=bits=wave_alloca(nbits);
        for(i=0;i<nbits;i++)
                {
                *pnt++=AN_X;
                }
        }

if((flags&(TR_ZEROFILL|TR_ONEFILL))&&(nbits>1)&&(t->n.nd->msi)&&(t->n.nd->lsi))
	{
	char whichfill = (flags&TR_ZEROFILL) ? AN_0 : AN_1;

	if(t->n.nd->msi > t->n.nd->lsi)
		{
		if(t->n.nd->lsi > 0)
			{
			pnt=wave_alloca(t->n.nd->msi + 1);

			memcpy(pnt, bits, nbits);

        		for(i=nbits;i<t->n.nd->msi+1;i++)
                		{
                		pnt[i]=whichfill;
                		}

			bits = pnt;
			nbits = t->n.nd->msi + 1;
			}
		}
		else
		{
		if(t->n.nd->msi > 0)
			{
			pnt=wave_alloca(t->n.nd->lsi + 1);

        		for(i=0;i<t->n.nd->msi;i++)
                		{
                		pnt[i]=whichfill;
                		}

			memcpy(pnt+i, bits, nbits);

			bits = pnt;
			nbits = t->n.nd->lsi + 1;
			}
		}
	}

if(flags&TR_INVERT)
        {
        xtab = xrev;
        }
        else
        {
        xtab = xfwd;
        }

newbuff=(char *)malloc_2(nbits+6); /* for justify */
if(flags&TR_REVERSE)
	{
	char *fwdpnt, *revpnt;

	fwdpnt=bits;
	revpnt=newbuff+nbits+6;
	/* for(i=0;i<3;i++) *(--revpnt)=xtab[0]; */
	for(i=0;i<3;i++) *(--revpnt)=xfwd[0];
	for(i=0;i<nbits;i++)
		{
		*(--revpnt)=xtab[(int)(*(fwdpnt++))];
		}
	/* for(i=0;i<3;i++) *(--revpnt)=xtab[0]; */
	for(i=0;i<3;i++) *(--revpnt)=xfwd[0];
	}
	else
	{
	char *fwdpnt, *fwdpnt2;

	fwdpnt=bits;
	fwdpnt2=newbuff;
	/* for(i=0;i<3;i++) *(fwdpnt2++)=xtab[0]; */
	for(i=0;i<3;i++) *(fwdpnt2++)=xfwd[0];
	for(i=0;i<nbits;i++)
		{
		*(fwdpnt2++)=xtab[(int)(*(fwdpnt++))];
		}
	/* for(i=0;i<3;i++) *(fwdpnt2++)=xtab[0]; */
	for(i=0;i<3;i++) *(fwdpnt2++)=xfwd[0];
	}

if(flags&TR_ASCII)
	{
	char *parse;
	int found=0;

	free_2(newbuff);
	newbuff=(char *)malloc_2(nbits+14); /* for justify */
	if(flags&TR_REVERSE)
		{
		char *fwdpnt, *revpnt;
	
		fwdpnt=(char *)bits;
		revpnt=newbuff+nbits+14;
		for(i=0;i<7;i++) *(--revpnt)=xfwd[0];
		for(i=0;i<nbits;i++)
			{
			*(--revpnt)=xtab[(int)(*(fwdpnt++))];
			}
		for(i=0;i<7;i++) *(--revpnt)=xfwd[0];
		}
		else
		{
		char *fwdpnt, *fwdpnt2;
	
		fwdpnt=(char *)bits;
		fwdpnt2=newbuff;
		for(i=0;i<7;i++) *(fwdpnt2++)=xfwd[0];
		for(i=0;i<nbits;i++)
			{
			*(fwdpnt2++)=xtab[(int)(*(fwdpnt++))];
			}
		for(i=0;i<7;i++) *(fwdpnt2++)=xfwd[0];
		}

	len=(nbits/8)+2+2;		/* $xxxxx */
	os=pnt=(char *)calloc_2(1,len);
	if(GLOBALS->show_base) { *(pnt++)='"'; }

	parse=(flags&TR_RJUSTIFY)?(newbuff+((nbits+7)&7)):(newbuff+7);
	cvt_gray(flags,parse,(flags&TR_RJUSTIFY)?((nbits+7)&~7):nbits);

	for(i=0;i<nbits;i+=8)
		{
		unsigned long val;

		val=0;
		for(j=0;j<8;j++)
			{
			val<<=1;

			if((parse[j]==AN_X)||(parse[j]==AN_Z)||(parse[j]==AN_W)||(parse[j]==AN_U)||(parse[j]==AN_DASH)) { val=1000; /* arbitrarily large */}
			if((parse[j]==AN_1)||(parse[j]==AN_H)) { val|=1; }
			}

		if (val) {
			if (val > 0x7f || !isprint(val)) *pnt++ = '.'; else *pnt++ = val;
			found=1;
		}

		parse+=8;
		}
	if (!found && !GLOBALS->show_base) {
		*(pnt++)='"';
		*(pnt++)='"';
	}

	if(GLOBALS->show_base) { *(pnt++)='"'; }
	*(pnt)=0x00; /* scan build : remove dead increment */
	}
else if((flags&TR_HEX)||((flags&(TR_DEC|TR_SIGNED))&&(nbits>64)&&(!(flags&(TR_POPCNT|TR_FFO)))))
	{
	char *parse;

	len=(nbits/4)+2+1;		/* $xxxxx */
	os=pnt=(char *)calloc_2(1,len);
	if(GLOBALS->show_base) { *(pnt++)='$'; }

	parse=(flags&TR_RJUSTIFY)?(newbuff+((nbits+3)&3)):(newbuff+3);
	cvt_gray(flags,parse,(flags&TR_RJUSTIFY)?((nbits+3)&~3):nbits);

	for(i=0;i<nbits;i+=4)
		{
		unsigned char val;

		val=0;
		for(j=0;j<4;j++)
			{
			val<<=1;

			if((parse[j]==AN_1)||(parse[j]==AN_H))
				{
				val|=1;
				}
			else
			if((parse[j]==AN_0)||(parse[j]==AN_L))
				{
				}
			else
			if(parse[j]==AN_X)
				{
				int match = (j==0) || ((parse + i + j) == (newbuff + 3));
				int k;
				for(k=j+1;k<4;k++)
					{
                                        if(parse[k]!=AN_X)
                                                {
                                                char *thisbyt = parse + i + k;
                                                char *lastbyt = newbuff + 3 + nbits - 1;
                                                if((lastbyt - thisbyt) >= 0) match = 0;
                                                break;
                                                }
					}
				val = (match) ? 16 : 21; break;
				}
			else
			if(parse[j]==AN_Z)
				{
				int xover = 0;
				int match = (j==0) || ((parse + i + j) == (newbuff + 3));
				int k;
                                for(k=j+1;k<4;k++)
                                        {
                                        if(parse[k]!=AN_Z)
                                                {
                                                if(parse[k]==AN_X)
                                                        {
                                                        xover = 1;
                                                        }
                                                        else
                                                        {
                                                        char *thisbyt = parse + i + k;
                                                        char *lastbyt = newbuff + 3 + nbits - 1;
                                                        if((lastbyt - thisbyt) >= 0) match = 0;
                                                        }
                                                break;
                                                }
                                        }

				if(xover) val = 21;
				else val = (match) ? 17 : 22;
				break;
				}
			else
			if(parse[j]==AN_W)
				{
				int xover = 0;
				int match = (j==0) || ((parse + i + j) == (newbuff + 3));
				int k;
                                for(k=j+1;k<4;k++)
                                        {
                                        if(parse[k]!=AN_W)
                                                {
                                                if(parse[k]==AN_X)
                                                        {
                                                        xover = 1;
                                                        }
                                                        else
                                                        {
                                                        char *thisbyt = parse + i + k;
                                                        char *lastbyt = newbuff + 3 + nbits - 1;
                                                        if((lastbyt - thisbyt) >= 0) match = 0;
                                                        }
                                                break;
                                                }
                                        }

				if(xover) val = 21;
				else val = (match) ? 18 : 23;
				break;
				}
			else
			if(parse[j]==AN_U)
				{
				int xover = 0;
				int match = (j==0) || ((parse + i + j) == (newbuff + 3));
				int k;
                                for(k=j+1;k<4;k++)
                                        {
                                        if(parse[k]!=AN_U)
                                                {
                                                if(parse[k]==AN_X)
                                                        {
                                                        xover = 1;
                                                        }
                                                        else
                                                        {
                                                        char *thisbyt = parse + i + k;
                                                        char *lastbyt = newbuff + 3 + nbits - 1;
                                                        if((lastbyt - thisbyt) >= 0) match = 0;
                                                        }
                                                break;
                                                }
                                        }

				if(xover) val = 21;
				else val = (match) ? 19 : 24;
				break;
				}
			else
			if(parse[j]==AN_DASH)
				{
				int xover = 0;
				int k;
                                for(k=j+1;k<4;k++)
                                        {
                                        if(parse[k]!=AN_DASH)
                                                {
                                                if(parse[k]==AN_X)
                                                        {
                                                        xover = 1;
                                                        }
                                                break;
                                                }
                                        }

				if(xover) val = 21;
				else val = 20;
				break;
				}
			}

		*(pnt++)=AN_HEX_STR[val];

		parse+=4;
		}

	*(pnt)=0x00; /* scan build : remove dead increment */
	}
else if(flags&TR_OCT)
	{
	char *parse;

	len=(nbits/3)+2+1;		/* #xxxxx */
	os=pnt=(char *)calloc_2(1,len);
	if(GLOBALS->show_base) { *(pnt++)='#'; }

	parse=(flags&TR_RJUSTIFY)
		?(newbuff+((nbits%3)?(nbits%3):3))
		:(newbuff+3);
	cvt_gray(flags,parse,(flags&TR_RJUSTIFY)?(((nbits+2)/3)*3):nbits);

	for(i=0;i<nbits;i+=3)
		{
		unsigned char val;

		val=0;
		for(j=0;j<3;j++)
			{
			val<<=1;

			if(parse[j]==AN_X) { val=8; break; }
			if(parse[j]==AN_Z) { val=9; break; }
			if(parse[j]==AN_W) { val=10; break; }
			if(parse[j]==AN_U) { val=11; break; }
			if(parse[j]==AN_DASH) { val=12; break; }

			if((parse[j]==AN_1)||(parse[j]==AN_H)) { val|=1; }
			}

		*(pnt++)=AN_OCT_STR[val];
		parse+=3;
		}

	*(pnt)=0x00; /* scan build : remove dead increment */
	}
else if(flags&TR_BIN)
	{
	char *parse;

	len=(nbits/1)+2+1;		/* %xxxxx */
	os=pnt=(char *)calloc_2(1,len);
	if(GLOBALS->show_base) { *(pnt++)='%'; }

	parse=newbuff+3;
	cvt_gray(flags,parse,nbits);

	for(i=0;i<nbits;i++)
		{
		*(pnt++)=AN_STR[(int)(*(parse++))];
		}

	*(pnt)=0x00; /* scan build : remove dead increment */
	}
else if(flags&TR_SIGNED)
	{
	char *parse;
	TimeType val = 0;
	unsigned char fail=0;

	len=21;	/* len+1 of 0x8000000000000000 expressed in decimal */
	os=(char *)calloc_2(1,len);

	parse=newbuff+3;
	cvt_gray(flags,parse,nbits);

        if((parse[0]==AN_1)||(parse[0]==AN_H))
                { val = LLDescriptor(-1); }
        else
        if((parse[0]==AN_0)||(parse[0]==AN_L))
                { val = LLDescriptor(0); }
        else
                { fail = 1; }

        if(!fail)
	for(i=1;i<nbits;i++)
		{
		val<<=1;

                if((parse[i]==AN_1)||(parse[i]==AN_H)) {  val|=LLDescriptor(1); }
                else if((parse[i]!=AN_0)&&(parse[i]!=AN_L)) { fail=1; break; }
		}

	if(!fail)
		{
		if((flags&TR_FPDECSHIFT)&&(t->t_fpdecshift))
			{
			cvt_fpsdec(t, val, os, len, nbits);
			}
			else
			{
                        if(!(flags&TR_TIME))
                                {
                                sprintf(os, TTFormat, val);
                                }
                                else
                                {
                                free_2(os);
                                os = calloc_2(1, 128);
                                reformat_time(os, val, GLOBALS->time_dimension);
                                }
			}
		}
		else
		{
		strcpy(os, "XXX");
		}
	}
else if(flags&TR_REAL)
	{
	char *parse;

	if((nbits==64) || (nbits == 32))
		{
		UTimeType utt = LLDescriptor(0);
		double d;
		float f;
		uint32_t utt_32;

		parse=newbuff+3;
		cvt_gray(flags,parse,nbits);

		for(i=0;i<nbits;i++)
			{
			char ch = AN_STR[(int)(*(parse++))];
			if ((ch=='0')||(ch=='1'))
				{
				utt <<= 1;
				if(ch=='1')
					{
					utt |= LLDescriptor(1);
					}
				}
				else
				{
				goto rl_go_binary;
				}
			}

		os=/*pnt=*/(char *)calloc_2(1,64); /* scan-build */

		if(nbits==64)
			{
			memcpy(&d, &utt, sizeof(double));
		dpr_e16(os, d); /* sprintf(os, "%.16g", d); */
		}
		else
		{
			utt_32 = utt;
			memcpy(&f, &utt_32, sizeof(float));
			sprintf(os, "%f", f);
			}
		}
		else
		{
rl_go_binary:	len=(nbits/1)+2+1;		/* %xxxxx */
		os=pnt=(char *)calloc_2(1,len);
		if(GLOBALS->show_base) { *(pnt++)='%'; }

		parse=newbuff+3;
		cvt_gray(flags,parse,nbits);

		for(i=0;i<nbits;i++)
			{
			*(pnt++)=AN_STR[(int)(*(parse++))];
			}

		*(pnt)=0x00; /* scan build : remove dead increment */
		}
	}
else	/* decimal when all else fails */
	{
	char *parse;
	UTimeType val=0;
	unsigned char fail=0;

	len=21; /* len+1 of 0xffffffffffffffff expressed in decimal */
	os=(char *)calloc_2(1,len);

	parse=newbuff+3;
	cvt_gray(flags,parse,nbits);

	for(i=0;i<nbits;i++)
		{
		val<<=1;

                if((parse[i]==AN_1)||(parse[i]==AN_H)) {  val|=LLDescriptor(1); }
                else if((parse[i]!=AN_0)&&(parse[i]!=AN_L)) { fail=1; break; }
		}

	if(!fail)
		{
		if((flags&TR_FPDECSHIFT)&&(t->t_fpdecshift))
			{
			cvt_fpsudec(t, val, os, len);
			}
			else
			{
                        if(!(flags&TR_TIME))
                                {
                                sprintf(os, UTTFormat, val);
                                }
                                else
                                {
                                free_2(os);
                                os = calloc_2(1, 128);
                                reformat_time(os, val, GLOBALS->time_dimension);
                                }
			}
		}
		else
		{
		strcpy(os, "XXX");
		}
	}

free_2(newbuff);
return(os);
}


char *convert_ascii_vec(Trptr t, char *vec)
{
char *s = convert_ascii_vec_2(t, vec);

if(!(t->f_filter|t->p_filter|t->e_filter))
	{
	if(GLOBALS->lz_removal) lzremoval(s);
	}
	else
	{
	if(t->e_filter)
		{
		s = edofilter(t, s);
		}
	else
	if(t->f_filter)
		{
		s = dofilter(t, s);
		}
		else
		{
		s = pdofilter(t, s);
		}
	}

return(s);
}

char *convert_ascii(Trptr t, vptr v)
{
char *s;

if((!t->t_filter_converted) && (!(v->flags & HIST_STRING)))
	{
	s = convert_ascii_2(t, v);
	}
	else
	{
	s = strdup_2((char *)v->v);

	if((*s == '?') && (!GLOBALS->color_active_in_filter))
	        {
	        char *s2a;
	        char *s2 = strchr(s+1, '?');
	        if(s2)
	                {
	                s2++;
	                s2a = malloc_2(strlen(s2)+1);
	                strcpy(s2a, s2);
	                free_2(s);
	                s = s2a;
	                }
	        }
	}

if(!(t->f_filter|t->p_filter|t->e_filter))
	{
	if(GLOBALS->lz_removal) lzremoval(s);
	}
	else
	{
	if(t->e_filter)
		{
		s = edofilter(t, s);
		}
	else
	if(t->f_filter)
		{
		s = dofilter(t, s);
		}
		else
		{
		s = pdofilter(t, s);
		}
	}

return(s);
}


/*
 * convert trptr+hptr vectorstring into a real
 */
double convert_real_vec(Trptr t, char *vec)
{
Ulong flags;
int nbits;
char *bits;
char *pnt, *newbuff;
int i;
const char *xtab;
double mynan = strtod("NaN", NULL);
double retval = mynan;

static const char xfwd[AN_COUNT]= AN_NORMAL  ;
static const char xrev[AN_COUNT]= AN_INVERSE ;

flags=t->flags;

nbits=t->n.nd->msi-t->n.nd->lsi;
if(nbits<0)nbits=-nbits;
nbits++;

if(vec)
        {
        bits=vec;
        if(*vec>AN_MSK)              /* convert as needed */
        for(i=0;i<nbits;i++)
                {
		vec[i] = cvt_table[(unsigned char)vec[i]];
                }
        }
        else
        {
        pnt=bits=wave_alloca(nbits);
        for(i=0;i<nbits;i++)
                {
                *pnt++=AN_X;
                }
        }


if(flags&TR_INVERT)
        {
        xtab = xrev;
        }
        else
        {
        xtab = xfwd;
        }

newbuff=(char *)malloc_2(nbits+6); /* for justify */
if(flags&TR_REVERSE)
	{
	char *fwdpnt, *revpnt;

	fwdpnt=bits;
	revpnt=newbuff+nbits+6;
	/* for(i=0;i<3;i++) *(--revpnt)=xtab[0]; */
	for(i=0;i<3;i++) *(--revpnt)=xfwd[0];
	for(i=0;i<nbits;i++)
		{
		*(--revpnt)=xtab[(int)(*(fwdpnt++))];
		}
	/* for(i=0;i<3;i++) *(--revpnt)=xtab[0]; */
	for(i=0;i<3;i++) *(--revpnt)=xfwd[0];
	}
	else
	{
	char *fwdpnt, *fwdpnt2;

	fwdpnt=bits;
	fwdpnt2=newbuff;
	/* for(i=0;i<3;i++) *(fwdpnt2++)=xtab[0]; */
	for(i=0;i<3;i++) *(fwdpnt2++)=xfwd[0];
	for(i=0;i<nbits;i++)
		{
		*(fwdpnt2++)=xtab[(int)(*(fwdpnt++))];
		}
	/* for(i=0;i<3;i++) *(fwdpnt2++)=xtab[0]; */
	for(i=0;i<3;i++) *(fwdpnt2++)=xfwd[0];
	}

if(flags&TR_REAL)
	{
	if((nbits==64) || (nbits == 32)) /* fail (NaN) otherwise */
		{
		char *parse;
		UTimeType val=0;
		unsigned char fail=0;
		uint32_t val_32;

		parse=newbuff+3;
		for(i=0;i<nbits;i++)
			{
			val<<=1;

	        if((parse[i]==AN_1)||(parse[i]==AN_H)) {  val|=LLDescriptor(1); }
	        else if((parse[i]!=AN_0)&&(parse[i]!=AN_L)) { fail=1; break; }
			}


                if(!fail)
                        {
                        if(nbits==64)
                                {
                                memcpy(&retval, &val, sizeof(double)); /* otherwise strict-aliasing rules problem if retval = *(double *)&val; */
                                }
                                else
                                {
                                float f;
                                val_32 = val;
                                memcpy(&f, &val_32, sizeof(float)); /* otherwise strict-aliasing rules problem if retval = *(double *)&val; */
                                retval = (double)f;
                                }
                        }
		}
	}
    else
    {
	if(flags&TR_SIGNED)
		{
		char *parse;
		TimeType val = 0;
		unsigned char fail=0;

		parse=newbuff+3;
		cvt_gray(flags,parse,nbits);

	        if((parse[0]==AN_1)||(parse[0]==AN_H))
	                { val = LLDescriptor(-1); }
	        else
	        if((parse[0]==AN_0)||(parse[0]==AN_L))
	                { val = LLDescriptor(0); }
	        else
	                { fail = 1; }

	        if(!fail)
		for(i=1;i<nbits;i++)
			{
			val<<=1;

	                if((parse[i]==AN_1)||(parse[i]==AN_H)) {  val|=LLDescriptor(1); }
	                else if((parse[i]!=AN_0)&&(parse[i]!=AN_L)) { fail=1; break; }
			}
		if(!fail)
			{
			retval = val;
			}
		}
	else	/* decimal when all else fails */
		{
		char *parse;
		UTimeType val=0;
		unsigned char fail=0;

		parse=newbuff+3;
		cvt_gray(flags,parse,nbits);

		for(i=0;i<nbits;i++)
			{
			val<<=1;

	                if((parse[i]==AN_1)||(parse[i]==AN_H)) {  val|=LLDescriptor(1); }
	                else if((parse[i]!=AN_0)&&(parse[i]!=AN_L)) { fail=1; break; }
			}
		if(!fail)
			{
			retval = val;
			}
		}
	}

free_2(newbuff);
return(retval);
}



/*
 * convert trptr+vptr into a real
 */
double convert_real(Trptr t, vptr v)
{
Ulong flags;
int nbits;
unsigned char *bits;
char *newbuff;
int i;
const char *xtab;
double mynan = strtod("NaN", NULL);
double retval = mynan;

static const char xfwd[AN_COUNT]= AN_NORMAL  ;
static const char xrev[AN_COUNT]= AN_INVERSE ;

flags=t->flags;
nbits=t->n.vec->nbits;
bits=v->v;

if(flags&TR_INVERT)
        {
        xtab = xrev;
        }
        else
        {
        xtab = xfwd;
        }

newbuff=(char *)malloc_2(nbits+6); /* for justify */
if(flags&TR_REVERSE)
	{
	char *fwdpnt, *revpnt;

	fwdpnt=(char *)bits;
	revpnt=newbuff+nbits+6;
	/* for(i=0;i<3;i++) *(--revpnt)=xtab[0]; */
	for(i=0;i<3;i++) *(--revpnt)=xfwd[0];
	for(i=0;i<nbits;i++)
		{
		*(--revpnt)=xtab[(int)(*(fwdpnt++))];
		}
	/* for(i=0;i<3;i++) *(--revpnt)=xtab[0]; */
	for(i=0;i<3;i++) *(--revpnt)=xfwd[0];
	}
	else
	{
	char *fwdpnt, *fwdpnt2;

	fwdpnt=(char *)bits;
	fwdpnt2=newbuff;
	/* for(i=0;i<3;i++) *(fwdpnt2++)=xtab[0]; */
	for(i=0;i<3;i++) *(fwdpnt2++)=xfwd[0];
	for(i=0;i<nbits;i++)
		{
		*(fwdpnt2++)=xtab[(int)(*(fwdpnt++))];
		}
	/* for(i=0;i<3;i++) *(fwdpnt2++)=xtab[0]; */
	for(i=0;i<3;i++) *(fwdpnt2++)=xfwd[0];
	}

if(flags&TR_REAL)
	{
	if((nbits==64) || (nbits == 32)) /* fail (NaN) otherwise */
		{
		char *parse;
		UTimeType val=0;
		unsigned char fail=0;
		uint32_t val_32;

		parse=newbuff+3;
		for(i=0;i<nbits;i++)
			{
			val<<=1;

		        if((parse[i]==AN_1)||(parse[i]==AN_H)) {  val|=LLDescriptor(1); }
		        else if((parse[i]!=AN_0)&&(parse[i]!=AN_L)) { fail=1; break; }
			}

                if(!fail)
                        {
                        if(nbits==64)
                                {
                                memcpy(&retval, &val, sizeof(double)); /* otherwise strict-aliasing rules problem if retval = *(double *)&val; */
                                }
                                else
                                {
                                float f;
                                val_32 = val;
                                memcpy(&f, &val_32, sizeof(float)); /* otherwise strict-aliasing rules problem if retval = *(double *)&val; */
                                retval = (double)f;
                                }
                        }
		}
	}
    else
    {
    if(flags&TR_SIGNED)
		{
		char *parse;
		TimeType val = 0;
		unsigned char fail=0;

		parse=newbuff+3;
		cvt_gray(flags,parse,nbits);

		if((parse[0]==AN_1)||(parse[0]==AN_H))
			{ val = LLDescriptor(-1); }
		else
		if((parse[0]==AN_0)||(parse[0]==AN_L))
			{ val = LLDescriptor(0); }
		else
			{ fail = 1; }

		if(!fail)
		for(i=1;i<nbits;i++)
			{
			val<<=1;
	
			if((parse[i]==AN_1)||(parse[i]==AN_H)) {  val|=LLDescriptor(1); }
			else if((parse[i]!=AN_0)&&(parse[i]!=AN_L)) { fail=1; break; }
			}

		if(!fail)
			{
			retval = val;
			}
		}
	else	/* decimal when all else fails */
		{
		char *parse;
		UTimeType val=0;
		unsigned char fail=0;
	
		parse=newbuff+3;
		cvt_gray(flags,parse,nbits);
	
		for(i=0;i<nbits;i++)
			{
			val<<=1;
	
			if((parse[i]==AN_1)||(parse[i]==AN_H)) {  val|=LLDescriptor(1); }
			else if((parse[i]!=AN_0)&&(parse[i]!=AN_L)) { fail=1; break; }
			}
	
		if(!fail)
			{
			retval = val;
			}
		}
	}

free_2(newbuff);
return(retval);
}

