
#include <stream.h>
#include <fstream.h>
#include <stdio.h>
#include <string.h>
#include "arthtyp.h"
#include "hrdarth.h"
#include "cgidbg.h"
#include "stattyp.h"
#include "attrib.h"

static char * DeleteTrailZero(char * Number)
{
	// LogOut << "DeleteTrailZero(" << Number << ")\n" ;
	char * WhereIsE = 0;
	char * LastZero = 0;
	int Length = strlen(Number);
	for (char * Ptr = Number+Length-1; Ptr >Number;Ptr--) {
		if (WhereIsE) {
			if (*Ptr == '0') LastZero = Ptr ;
			else break;
		} else if (*Ptr == 'e' || *Ptr == 'E') WhereIsE = Ptr ;
	}
	if (WhereIsE && LastZero) while (*WhereIsE)
		*LastZero++ = *WhereIsE++;
	if (LastZero) *LastZero = '\0' ;
	return Number ;
}

const char * FullFloatValue(float x)
{
	// LogOut << "FullFloatValue\n" ;
	double y = x ;
	// LogOut << "x = " << x << "\n" ;
	// LogOut << "y = " << y << "\n" ;
	static char Buf[32];
	sprintf(Buf,"%.8e",y);
	DeleteTrailZero(Buf);
	int ExpBase = strlen(Buf) - 4 ;
	if (!strcmp(Buf+ExpBase,"e+00")) Buf[ExpBase] = '\0' ;
	return Buf ;
}

const char * FullDoubleValue(double x)
{
	static char Buf[32];
	sprintf(Buf,"%.18e",x);
	DeleteTrailZero(Buf);
	int ExpBase = strlen(Buf) - 4 ;
	if (!strcmp(Buf+ExpBase,"e+00")) Buf[ExpBase] = '\0' ;
	return Buf ;
}

enum BaseTypes { NullBaseType=0, int16Type, int32Type, floatType, doubleType,
	ArithDependentType,  EndArithType };


struct StaticValueOptions {
	const char * Name ;
	int NumberOfValues ;
	BaseTypes TheType ;
	BaseTypes * BaseTypeTable ;
	const char * InitType;
};


static BaseTypes MachWordTable[ArithType::MaxArithTypes+1] = {NullBaseType} ;
static BaseTypes AccMachWordTable[ArithType::MaxArithTypes+1] = {NullBaseType} ;

static StaticValueOptions TheStaticValueOptions[] = {
	{ "MachWord",	1,	ArithDependentType,	MachWordTable,
							"MachWordType"},
	{ "AccMachWord",1,	ArithDependentType,	AccMachWordTable,
							"AccMachWordType"},
	{ "CxMachWord",	2,	ArithDependentType,	MachWordTable,
							"MachWordType"},
	{ "CxAccMachWord",2,	ArithDependentType,	AccMachWordTable,
							"AccMachWordType"},
	{ "float",	1,	floatType,		0},
	{ "double",	1,	doubleType,		0},
	{ "complex",	2,	doubleType,		0},
	{ "int",	1,	int32Type,		0},
	{ "int16",	1,	int16Type,		0},
	{ "int32",	1,	int32Type,		0},
	{0},
};


static void InitMachWordTables()
{
	MachWordTable[0] = EndArithType ; // should not be used
	MachWordTable[ArithType::ArithDouble] = doubleType ;
	MachWordTable[ArithType::ArithInt16] = int16Type ;
	MachWordTable[ArithType::ArithInt32] = int32Type ;
	MachWordTable[ArithType::ArithFloat] = floatType ;

	AccMachWordTable[0] = EndArithType ; // should not be used
	AccMachWordTable[ArithType::ArithDouble] = doubleType ;
	AccMachWordTable[ArithType::ArithInt16] = int32Type ;
	AccMachWordTable[ArithType::ArithInt32] = int32Type ;
	AccMachWordTable[ArithType::ArithFloat] = floatType ;

}

static class Dummy {
public:
	Dummy(){InitMachWordTables();}
} TheDummy ;


StaticValueOptions& GetStaticValueOption(const char * Type)
{
	for (StaticValueOptions * Opts = TheStaticValueOptions ; Opts->Name;
		Opts++) if (!strcmp(Opts->Name,Type)) return *Opts ;
	TheLog << "Bad option `" << Type << "'\n" ;
	DbgError("GetStaticValueOption","bad type");
	return *Opts ; // TO ELIMINATE WARNING, NEVER EXECUTED
}

const char * GetStatInitName(const char * TypeName)
{
	// cerr << "GetStaticInitName(" << TypeName << ")\n" ;
	const char * InitType = GetStaticValueOption(TypeName).InitType ;
	if (InitType) TypeName = InitType ;
	// cerr << "Returning " << TypeName << "\n" ;
	return TypeName ;
}

int GetStaticElementSize(const char * TypeName)
{
	return GetStaticValueOption(TypeName).NumberOfValues ;
}


const MaxStringLength = 256 ;

void OutStringStaticValue(ostream& Out, const char * TypeName,
	void * Value)
{
	// LogOut << "OutStringStaticValue(," << TypeName << ",)\n" ;
	StaticValueOptions& Opt = GetStaticValueOption(TypeName);
	for (int ix = 0 ; ix < Opt.NumberOfValues ; ix++) {
		int NotDone = 1 ;
		BaseTypes TheType = Opt.TheType ;
		while (NotDone) {
/*
 *			LogOut << "TheType = " << TheType << ", NotDone = "
 *				<< NotDone << "\n" ;
 */
			NotDone = 0 ;
			switch (TheType) {
case int16Type :
				Out << *(((int16 *) Value) + ix);
				break ;
case int32Type :
				Out << *(((int32 *) Value) + ix);
				break ;
case floatType :
				Out << FullFloatValue(*(((float *) Value)+ix));
				break ;
case doubleType :
				Out <<
				    FullDoubleValue(*(((double *) Value) + ix));
				break ;
case ArithDependentType :
				TheType = Opt.BaseTypeTable[TheArithType];
				NotDone = 1 ;
				continue ;
case EndArithType:
case NullBaseType:
default:
				DbgError("StringStaticValue","bad type");
			}
		}
		if (ix < Opt.NumberOfValues-1) Out << ", " ;
	}
}



