/*  intfc2.c   */
/*  Copyright 1989 Mountain Math Software  */
/*  All Rights Reserved                    */
#include <unistd.h>
#include <stream.h>
#include <string.h>
#include <ctype.h>
#include <complex.h>
#include <time.h>
#include <stdlib.h>
#ifdef __NT_VC__
#include <io.h>
#endif

// #include "sysintfc.h"
 
#include "intfc.h"
#include "user.h"

// #include "menu.h"
#include "array.h"
#include "outtok.h"
#include "outtokf.h"
#include "usercom.h"
#include "baseio.h"
#include "yacintfc.h"
#include "sigintfc.h"
#include "decptr.h"
#include "cgidbg.h"
#include "hrdarth.h"
#include "dsp.h"
#include "dspconst.h"
#include "interp.h"
#include "tarparm.h"
// #include "travparm.h"
#include "tarnodpar.h"
#include "dfnode.h"
#include "dirfil.h"
#include "mkstr.h"
#include "network.h"
#include "dspe_app.h"

// void TestAlloc(const char *msg);

static const char * ExecuteTypeName(NodeExecuteType type)
{
	switch (type) {
case NodeExecuteFixedBound:
		return "NodeExecuteFixedBound" ;
case NodeExecuteSpaceBound:
		return "NodeExecuteSpaceBound" ;
case NodeExecuteFixedIgnoreSpace:
		return "NodeExecuteFixedIgnoreSpace" ;
default:
		DbgError("ExecuteTypeName","bad argument");
	}
	return 0 ;
}


UserBasicObjects::UserBasicObjects(const char *Name,ValueType val,DecType Dec)
{
	TypeName = Name ;
	AliasList = new StringList ;
	Objects = new SimpleUserObjectList ;
	ThisType = val ;
	Type = Dec;
}

/*
 * static void OutBracketedValue(OutTokens& Out, int32 Val)
 * {
 *	char Buf[32];
 *	Out.NextConcat("[");
 *	Out.NextConcat(strcpy(Buf,dec(Val)));
 *	Out.NextConcat("]");
 * }
 */

static int LocalParameterName(const char * Name)
{
	return !strncmp(TheArrayDataName,Name,strlen(TheArrayDataName));
}


static int force_list = 0 ;
int SimpleUserObject::CppList(OutTokens& Out)
{
	if (!force_list) if (no_cpp_dump) return 1 ;
	int OK = 1;
	// LogOut << "SimpleUserObject::CppList - " << TypeName << " " << Name
	//	<< "\n" ;
	int ArraySize = 0;
	if (GetArray()) ArraySize = GetArraySize();
	if (ArraySize) {
		if (LocalParameterName(Name)) return 1 ;
		Out.NextFillOut(TypeName);
		// Out.NextFillOut("*");
		Out.NextFillOut(Name);
		Out.NextFillOut("[] = {");
		OK = GetArray()->CppList(Out,CppListState);
		Out.NextFillOut("} ;");
		Out.NewLine();
		return OK ;
	}
	Out.NextFillOut(TypeName);
	Out.NextFillOut(Name);
	Out.NextFillOut("=");
	OK = Value.CppList(Out,-1);
	Out.NextFillOut(";");
	if (!Value.ValueDefined) Out.NextConcat("\t\t// UNDEFINED");
		// double tab to try and align comments
	else if (IsMachWordType(Value.Type)) {
	    	ArithType::ArithTypes LocalTheArithType = DecTypeToArithType(
				Value.Type) ;
	    	if (LocalTheArithType == ArithType::ArithInt16 ||
				LocalTheArithType == ArithType::ArithInt32) {
			char Buf[32];
			Out.NextConcat("\t\t// is 0x");
			int32 Val = (int32) ConvertToDouble(Value);
			Out.NextConcat(strcpy(Buf,hex(Val)));
			Out.NextConcat(" (");
			Out.NextConcat(strcpy(Buf,dec(Val)));
			Out.NextConcat(")");
		}
	}
	Out.NewLine();
	return OK ;
}

static void DumpArray(ArrayData * data, OutTokens& Out)
{
	Out.NewLine();
	Out.NextFillOut("Array:");
	Out.NextFillOut("Size = ");
	char Buf[32];
	strcpy(Buf,dec(data->GetArraySize()));
	Out.NextFillOut(Buf);
}

void SimpleUserObject::Dump(OutTokens& Out,class ValueTypeList * Lst)
{
	Out.NextFillOut(TypeName);
	Out.NextFillOut(Name);
	Out.NextFillOut("=");
	if (!Value.ValueDefined) Out.NextConcat("(UNDEFINED)");
	Value.Dump(Out,Lst);
	if (GetArray()) DumpArray(GetArray(),Out);
	else Out.NextFillOut("SCALAR");
	Out.NewLine();
}

void SimpleUserObjectList::Dump(OutTokens& Out,ValueTypeList * Lst)
{
	SimpleUserObjectIterator Next(*this) ;
	SimpleUserObject * Obj;
	while (Obj = Next()) Obj->Dump(Out,Lst) ;
}

int SimpleUserObjectList::Remove(const char * Name)
{
	SimpleUserObjectIterator Next(*this);
	SimpleUserObject * Obj ;
	while (Obj = Next()) if (!strcmp(Obj->GetName(),Name))
		return Remove(Obj);
	return 0;
}

int SimpleUserObjectList::Remove(SimpleUserObject * Obj)
{
	return RemoveEntry(Obj) == OK;
}

void UserBasicObjects::Describe(OutTokens& Out, ListEntity ListOut)
{
	if (AliasList->Size()) {
		if (AliasList->Size()==1) 
			Out.NextFillOut("The alias for this type is:");
		else Out.NextFillOut("The aliases for this type are:");
		Out.NewLine();
		StringListIterator Next(*AliasList) ;
		const char * name ;
		while (name = Next()) Out.NextFillOut(name) ;
		Out.NewLine();
	}
	if (!Objects->Size()) {
		Out.NextFillOut("No ");
		Out.NextQuoteOut(TypeName);
		Out.NextFillOut(" objects have been declared.") ;
		Out.NewLine() ;
		return ;
	}
	Out.NextFillOut( "Following is a list of all " );
	Out.NextQuoteOut(TypeName);
	Out.NextFillOut( " objects.") ;
	Out.NewLine() ;
	Objects->Describe(Out,ListOut) ;
}

ValueType * UserBasicObjects::FindObj(const char * Name)
{
	SimpleUserObjectIterator Next(*Objects);
	SimpleUserObject * Obj ;
	while (Obj=Next()) if (!strcmp(Name,Obj->GetName()))
		return Obj->GetValue() ;
	return 0;
}
	

int UserBasicObjects::Remove(const char * Name)
{
	return Objects->Remove(Name);
}

int UserBasicObjects::Remove(SimpleUserObject * Obj)
{
	return Objects->Remove(Obj);
}

ValueType * UserBasicObjects::Find(const char * Name)
{
	if (!strcmp(Name,TypeName)) return &ThisType ;
	StringListIterator Next(*AliasList) ;
	char * alias ;
	while (alias = Next()) if (!strcmp(alias,Name)) return &ThisType;
	return 0;
}

UserEntity * InteractiveEntityList::GetObject(const char * name)
{
	InteractiveEntityIterator Next(*this) ;
	InteractiveEntity * Ent ;
	UserEntity * Ret ;
	while (Ent=Next()) if (Ret = Ent->GetObject(name)) return Ret;
	return 0;
}

ValueType * InteractiveEntityList::FindTypeObj(const char * name)
{
	InteractiveEntityIterator Next(*this) ;
	InteractiveEntity * Ent ;
	ValueType * Ret ;
	while (Ent=Next()) if (Ret = Ent->FindTypeObj(name)) return Ret;
	return 0;
}
	
InteractiveEntity * InteractiveEntityList::FindObjEnt(const char * name)
{
	InteractiveEntityIterator Next(*this) ;
	InteractiveEntity * Ent ;
	ValueType * Ret ;
	while (Ent=Next()) if (Ret = Ent->FindObj(name)) return Ent;
	return 0;
}
	
ValueType * InteractiveEntityList::FindObj(const char * name)
{
	InteractiveEntityIterator Next(*this) ;
	InteractiveEntity * Ent ;
	ValueType * Ret ;
	while (Ent=Next()) if (Ret = Ent->FindObj(name)) return Ret;
	return 0;
}
	


InteractiveEntity * InteractiveGlobal::GetInteractiveEntityFromObj
	(const char * Name)
{
	for (InteractiveEntityList ** Ptr = AllEntities; *Ptr; Ptr++) {
/*
 *	  	LogOut << "Searching list " <<
 *			(*Ptr)->GetBaseClassName() << "\n" ;
 */
		InteractiveEntity * Search =(*Ptr)->FindObjEnt(Name);
		if (Search) return Search ;
	}
	return 0;
}

UserEntity * InteractiveGlobal::GetObject(const char * Name)
{
	for (InteractiveEntityList ** Ptr = AllEntities; *Ptr; Ptr++) {
		UserEntity * Return = (*Ptr)->GetObject(Name);
		if (Return) return Return ;
	}
	return 0;
}
	
InteractiveEntity * InteractiveGlobal::GetInteractiveEntity(const char * Name)
{
	for (InteractiveEntityList ** Ptr = AllEntities; *Ptr; Ptr++) {
/*
 *		LogOut << "Searching list " <<
 *			(*Ptr)->GetBaseClassName() << "\n" ;
 */
		InteractiveEntity * Search =(*Ptr)->Find(Name);
		if (Search) return Search ;
	}
	return 0;
}


ValueType * InteractiveGlobal::CheckDeclarator(const char * name)
{
	UserBasicObjects ** Basic = AllBasicObjs ;
	ValueType * Val ;
	while (*Basic) if (Val = (*Basic++)->Find(name)) {
		ValueType * NewVal = new ValueType ;
		*NewVal = *Val ;
			// need to set alias name
 		SimpleUserObject * Simp = new SimpleUserObject(
 			strcpy(new char[strlen(name)+1],name),0,*NewVal);
		NewVal->Value.Obj = Simp ;
		return NewVal ;
	}
	InteractiveEntityList ** TheList = AllEntities ;
	InteractiveEntity * IntEnt = 0 ;
	while (*TheList) if ((IntEnt = (*TheList++)->Find(name))) break ;
	if (!IntEnt) return 0;
	return IntEnt->GetValue() ;	
}

ValueType * InteractiveGlobal::CheckNewDeclaration(const char * name)
{
	ValueType * ValPt = CheckDeclaration(name) ;
	if (!ValPt) return 0;
	ValueType * Copy = new ValueType(ValPt) ;
	return Copy ;
}

ValueType * InteractiveGlobal::GetType(const char * name)
{
	UserBasicObjects ** Basic = AllBasicObjs ;
	while (*Basic) if ((*Basic)->FindObj(name))
		return (*Basic)->GetValueType() ;
	else Basic++;
	InteractiveEntityList ** TheList = AllEntities ;
	ValueType * Found ;
	while (*TheList) if (Found =(*TheList)->FindTypeObj(name))
		return Found ;
	else TheList++ ;
	return 0;
}

ValueType * InteractiveGlobal::CheckDeclaration(const char * name)
{
	UserBasicObjects ** Basic = AllBasicObjs ;
	ValueType * Val ;
	while (*Basic) if (Val = (*Basic++)->FindObj(name))
		return Val ;
	InteractiveEntityList ** TheList = AllEntities ;
	while (*TheList) if ( Val =(*TheList++)->FindObj(name)) {
		if (Val->Type != DecEnt && Val->Type != DecDspPP)
			DbgError("InteractiveGlobal::CheckDeclaration",
				"bad type");
		Val->Value.ValEnt->ClearUnusedDefault();
		return Val ;
	}
	return 0;
}

char * InUseString[] = {
	"",
	"an object",	"an object class",		"an object base class",
	"a simple variable",	"a simple variable type",
	"an alias for a simple variable type",
	"a C++ reserved word" } ;

char * InteractiveGlobal::make_valid_name(char * base)
{
	if (!CheckNameInUse(base) == InUseNo) return base ;
	char * ret = make_valid_name((const char *) base);
	delete base ;
	return ret ;
}

char * InteractiveGlobal::make_valid_name(const char * base)
{
	char * check = DspApplication::force_to_legal_name(base);
	if (!check) return Concatenate(base);
	return check ;
/**********
	char * node_name = Concatenate(base);
	while (CheckNameInUse(node_name) != InUseNo) {
        char temp[2] ;
        temp[0] = (char)(mrand48() & 16) + 'a' ;
        temp[1] = '\0' ;
        if (strlen(node_name) > 36) node_name[20] = '\0' ;
        char * new_name = Concatenate(node_name,temp);
        delete node_name ;
        node_name = new_name ;
    }
	return node_name ;
 ************/
}

NameInUse InteractiveGlobal::CheckNameInUse(const char * name)
{
	UserBasicObjects ** Basic = AllBasicObjs ;
	ValueType * Val ;
	while (*Basic) {
		// LogOut <<"Checking for:" << (*Basic)->GetTypeName() << "\n" ;
		if (!strcmp((*Basic)->GetTypeName(),name))
			return InUseBasicType ;
		StringListIterator Next(*(*Basic)->GetAliasList()) ;
		char * Alias ;
		while (Alias = Next()) if (!strcmp(Alias,name))
			return InUseAliasType;
		// LogOut << "After alias check\n" ;
		if (Val = (*Basic++)->FindObj(name)) return InUseBasic ;
	}
	// LogOut << "Not a basic object\n" ;
	InteractiveEntityList ** TheList = AllEntities ;
	while (*TheList) {
		if ( !strcmp((*TheList)->GetBaseClassName(),name))
			return InUseEntityBaseType ;
		InteractiveEntityIterator Next(**TheList) ;
		InteractiveEntity * Ent ;
		while (Ent = Next()) if (!strcmp(Ent->GetClassName(),name))
			return InUseEntityType ;
		if ( Val =(*TheList++)->FindObj(name)) return InUseEntity ;
	}
	if (CheckReserved(name)) return InUseCReserved ;
	return InUseNo;
}

const NumInteractiveEntities = 9 ;
const NumBasicObjects = 7 ;

static char * ReservedC[] = {
	//          .           .           .           .
	"asm",      "auto",     "break",    "case",	"char",
	"class",    "const",	"complex",  "continue", "default",
	"delete",
	"do",	    "double",   "else",	    "enum",	"extern",
	"float",    "for",	"friend",   "goto",	"if",
	"inline",   "int",	"long",	    "new",	"operator",
	"overload", "public",	"register", "return",	"short",
	"sizeof",   "static",	"struct",   "switch",	"this",
	"typedef",  "union",	"unsigned", "virtual",	"void",
	"while",    "AccMachWord",	    "CxAccMachWord",
	"CxMachWord",	        "MachWord",
	0
};

int CheckReserved(const char * name)
{
	char **  pt = ReservedC ;
	while (*pt) if (!strcmp(*pt++,name)) return 1;
	return 0;
}

/*
 * void static DumpAll()
 * {
 *	LogOut << "Dump of Un's from intfc2.c\n";
 *	LogOut << "Nodes are 0x" << hex((long) UnTheNodes.EntityList) << "\n" ;
 *	LogOut << "CmpdNodes are 0x" << hex((long) UnTheCmpdNodes.EntityList)
 *		<< "\n" ;
 *	LogOut << "Displays are 0x" << hex((long) UnTheDisplays.EntityList)
 *		<< "\n"  ;
 *	LogOut << "Signals are 0x" << hex((long) UnTheSignals.EntityList)
 *		<< "\n"  ;
 *	LogOut << "Nets are 0x" << hex((long) UnTheNets.EntityList) << "\n"  ;
 * }
 */

static void SubClassInit()
{
	// LogOut << "SubClassInit\n" ;

	TheNodes->Append(new InteractiveEntity("DfNode",new EntityList,
		0, InteractiveNode));

/*
 *	TheNodes->Append(new InteractiveEntity("Display",new EntityList,
 *		0, InteractiveNode,0,"DfNode"));
 *	// +***********change DfNode to Node when these are put in .usr files
 *
 *	TheNodes->Append(new InteractiveEntity("GenericPlot",new EntityList,
 *		0, InteractiveNode,0,"Display"));
 *
 *
 *	TheNodes->Append(new InteractiveEntity("GenericBlockPlot",
 *		new EntityList, 0, InteractiveNode,0,"Display"));
 *
 *	TheNodes->Append(new InteractiveEntity("Signal",new EntityList,
 *		0, InteractiveNode,0,"DfNode"));
 */
	// +***********change DfNode to Node when these are put in .usr files

	// LogOut << "SubClassInit exit\n" ;
}

// LogMsg("Initing user basic object:",STR_TYPE);

/*
 * #define SETUP_USER_BASIC_OBJECT(TYPE,ENUM_TYPE,STR_TYPE,INIT)	\
 *	{	LogOut << "DK1\n" ;					\
 *	ValueType VTemp = *(new ValueType(ENUM_TYPE,			\
 *		*(new DataValue((TYPE) INIT)),DoDeclBasic));		\
 *	LogOut << "Dk2\n" ;						\
 *	Temp = AllUser[i++] =new UserBasicObjects(STR_TYPE,		\
 *		VTemp,ENUM_TYPE);					\
 *	(*(Temp->GetValueType())).Declared = Temp ;			\
 *	LogOut << "Dk3\n" ;}			
 */


#define SETUP_USER_BASIC_OBJECT(TYPE,ENUM_TYPE,STR_TYPE,INIT)		\
	{ DataValue * Temp2 = new DataValue((TYPE) INIT);		\
	ValueType VTemp = new ValueType(ENUM_TYPE,*Temp2,		\
		DoDeclBasic);						\
	Temp = AllUser[i++] =new UserBasicObjects(STR_TYPE,		\
		VTemp,ENUM_TYPE);					\
	(*(Temp->GetValueType())).Declared = Temp ;}



void InteractiveInit()
{
	// LogMsg("InteractiveInit Called");
	if (AllEntityLists) return ;
	int i;
	// LogOut << "Declaring " << NumBasicObjects+1 << "objects\n" ;
	UserBasicObjects ** AllUser =
		new UserBasicObjects * [NumBasicObjects+1] ;
	// LogOut << "AllUser = 0x" << hex((long)AllUser) << "\n" ;
	i = 0 ;
	UserBasicObjects * Temp ;

	SETUP_USER_BASIC_OBJECT(int32,DecInt,"int",0);
	Temp->AliasAppend("int32") ;

	SETUP_USER_BASIC_OBJECT(double,DecFloat,"double",0.0);
	Temp->AliasAppend("float") ;
	ValueType Pi(DecFloat, DoublePi, DeclBasic) ;
	Pi.ValueDefined = 1 ;
		// calculated with bc
	SimpleUserObject * PiSimp = new SimpleUserObject("double","Pi", Pi,0,1) ;
	Temp->ObjectAppend(PiSimp) ;
	PiSimp->GetValue()->Declared.Basic = PiSimp ;

	
	SETUP_USER_BASIC_OBJECT(void *,DecComplex,"complex",(new complex));
	SETUP_USER_BASIC_OBJECT(void *,DecMachWord,"MachWord",
		(new MachWord));
	SETUP_USER_BASIC_OBJECT(void *,DecAccMachWord,"AccMachWord",
		(new AccMachWord));
	char * CxxTest = new char[4] ;
	CxMachWord * Wrd = new CxMachWord ;
	SETUP_USER_BASIC_OBJECT(void *,DecCxMachWord,"CxMachWord",Wrd);
	SETUP_USER_BASIC_OBJECT(void *,DecCxAccMachWord,
		"CxAccMachWord", (new CxAccMachWord));

	AllUser[i] = 0;
	if (i != NumBasicObjects)
		DbgError("InteractiveInit","AllUser count off");
	InteractiveEntityList ** All = new
		InteractiveEntityList * [NumInteractiveEntities+1] ;
	i = 0 ;
	TheNodes = new InteractiveEntityList("DfNode");
	TheCmpdNodes = new InteractiveEntityList("CmpdNode");
	TheNets = new InteractiveEntityList("Networks");
	TheBuffers = new InteractiveEntityList("Buffers");
	TheSchedulers = new InteractiveEntityList("Schedulers");
	TheSignals = new InteractiveEntityList("Signals");
	TheDisplays = new InteractiveEntityList("Displays");
	TheProcedures = new InteractiveEntityList("Procedures");
	TheMiscellaneousClasses = new InteractiveEntityList("Miscellaneous");
	All[InteractiveNode] = UnTheNodes.Set(TheNodes); i++;
	All[InteractiveCmpdNode] = UnTheCmpdNodes.Set(TheCmpdNodes) ; i++;
	All[InteractiveNet] = UnTheNets.Set(TheNets); i++;
	All[InteractiveBuffer] = TheBuffers ; i++;
	All[InteractiveScheduler] = TheSchedulers ; i++;
	All[InteractiveSignal] = UnTheSignals.Set(TheSignals) ; i++;
	All[InteractiveDisplay] = UnTheDisplays.Set(TheDisplays) ; i++;
	All[InteractiveProcedure] = TheProcedures ; i++;
	All[InteractiveMiscellaneous] = TheMiscellaneousClasses ; i++ ;
	All[InteractiveTypeEnd] = 0 ;
	// DumpAll();
	if (i != NumInteractiveEntities)
		DbgError("InteractiveInit","All count off");
	AllEntityLists = new InteractiveGlobal(All,AllUser,ReservedC) ;
	SubClassInit();
}

InteractiveEntityList * InteractiveGlobal::GetInteractiveEntityList(
	InteractiveType type)
{
	if (type < 0 || type >= InteractiveTypeEnd) DbgError(
		"InteractiveGlobal::GetInteractiveEntityList","bad index");
	return AllEntities[type];
}


int InteractiveGlobal::CppList(const char * name)
{
	int OK = 1;
	OutTokens Out(OutputHelp);
	UserBasicObjects ** Ptr = AllBasicObjs ;
	while (*Ptr) if(!strcmp(name,(*Ptr)->GetTypeName())) {
		force_list = 1 ;
		OK &= (*Ptr)->CppList(Out) ;
		force_list = 0 ;
		return OK ;
	} else Ptr++ ;
	DbgError("InteractiveGlobal::BasicList","Missing type");
	return 0;
}

void InteractiveGlobal::EntityList(ListEntity ToDo)
{
	InteractiveEntityList ** Ptr = AllEntities ;
	const char * name ;
	for (;;) {
		*Output + OutputHelp << "The base classes are:\n" ;
		OutTokens Out(OutputHelp) ;
		while (*Ptr) Out.NextFillOut( (*Ptr++)->GetBaseClassName());
		Out.NewLine() ;
		if (ToDo == ListGlobalClasses) break ;
		name = GetName("class name or RETURN");
		if (!strlen(name)) break ;
		Ptr = AllEntities ;
		while (*Ptr)  if (!strcmp(name,(*Ptr)->GetBaseClassName()))
		{(*Ptr)->Describe(Out,ToDo); break ;}
		else Ptr++;
		if (*Ptr) break ;
		*Output + OutputHelp << "There is no class `" <<
			name << "'.\n" ;
	}
	delete (char *) name ;
}


UserEntity * InteractiveEntity::Declare(ValueType * Obj)
{
	if (!Obj) DbgError("InteractiveEntity::Declare","NULL Obj");
	
	// Match consistency of parameters - prompt user to
	// supply missing parameters or ones that fails consistency
	// check do this in class UserParameter
	if (!Parameters->SetValues(EntityInstances->Size(), Obj)) return 0;

	// Do the actual declaration by appending object to appropraite
	// list
	OutTokens Out(OutputHelp) ; // this should not be used 
	UserEntity * RetVal = Create(Out);
/*
 *	ValueType * Temp = new ValueType (DecEnt,RetVal,DoDeclEntity,this);
 *	Temp->ValueDefined=1;
 *	RetVal->SetClass(Temp);
 *	delete Temp ;
 */
	MakeDeclaredEntity(RetVal,this);
	return RetVal ;
}

int InteractiveGlobal::RemoveSimpleUserObject(SimpleUserObject * Obj)
{
	for (UserBasicObjects ** TheObjListArray = GetUserBasicObjects();
		*TheObjListArray; TheObjListArray++)
		if ((*TheObjListArray)->Remove(Obj)) return 1;
	return 0;
}

int InteractiveGlobal::RemoveSimpleUserObject(const char * Obj)
{
	for (UserBasicObjects ** TheObjListArray = GetUserBasicObjects();
		*TheObjListArray; TheObjListArray++)
		if ((*TheObjListArray)->Remove(Obj)) return 1;
	return 0;
}


int InteractiveGlobal::SaveState(OutTokens& Out,CppListCmds Cmd) 
{
	// LogOut << "InteractiveGlobal::SaveState\n" ;
	int Ok = 1;
	for (InteractiveEntityList ** Ptr = AllEntities; *Ptr; Ptr++) {
		// LogOut << "Saving\n" ;
		int Error = (*Ptr)->SaveState(Out,Cmd);
		Ok &= Error ;
	}
	return Ok ;
}

int InteractiveGlobal::save_state_kernel(OutTokens& Out)
{
	Out.NextFillOut("// DSP++ objects created at");
	long TheTime = time((long *)0) ;
	Out.NextFillOut(ctime(&TheTime));
	Out.NewLine();
	int Ok = 1 ;
	int Error ;
	for (UserBasicObjects ** Basic = AllBasicObjs ;*Basic; Basic++) {
		Error = (*Basic)->CppList(Out);
		Ok &= Error ;
	}

	Error = SaveState(Out,CppClearDecFlag);
	Ok &= Error ;
	ArrayDataIndexBase = ArrayDataIndex;
	Error = SaveState(Out,CppListCtor);
	Ok &= Error ;
	Error = SaveState(Out,CppListState);
	Ok &= Error ;
	Error = SaveState(Out,CppClearDecFlag);
	Ok &= Error ;

	Out.NextFillOut("// End DSP++ objects") ;
	Out.NewLine();
	Out.NextFillOut(";");
	Out.NewLine();
	return Ok ;
}

void InteractiveGlobal::SaveState(const char * SaveFileName)
{
	// LogOut << "InteractiveGlobal::SaveState(" << SaveFileName << ")\n" ;
	#define template "stat.XXXXXX"
	static char TempFileName[sizeof(template) + 1] ;
	
	strcpy(TempFileName, template);
	mktemp(TempFileName);
	OutTokFile * Out = OutTokFile::open_tok_file(TempFileName," ",60);
	if (!Out) return ;
	int Error = 0 ;
	int Ok = save_state_kernel(*Out);
	OutTokFile::delete_tok_file(Out) ; // Close File
	// LogOut << "Out deleted\n" ;
	int VersionFile = !FindLastDot(SaveFileName) ;
	if (!Ok) *Output + OutputCppHelp <<
	     "The current state of all objects cannot be saved.\n" <<
	     "No previous versions of the objects will be deleted.\n" ;
	else {
		if (!SaveFileName) Ok = 0 ;
		if (!*SaveFileName) Ok = 0 ;
		// rename file
		Error = 0 ;
		if (Ok) if (VersionFile) {
			char * Directory = FindDirectory(SaveFileName);
			char * Base = ReplaceDirectory(0,SaveFileName);
			ExamineDirectory Exam(Directory,0,Base);
			Error = !Exam.NewVersion(TempFileName,
				State.GetVersions());
			delete Base ;
			delete Directory ;
		}
		if (Error) Ok = 0 ;

	}
	if (!Ok) {
		*Output + OutputCppHelp <<
			"Any DSP++ objects that were saved are in `"
			<< TempFileName << "'.\n" ;
		DspExecState->InformationComplete();
		return ;
	}
	if (!VersionFile) { 
		HelpOut << "`" << SaveFileName << "'\n" ;
		HelpOut <<
		"contains a `.' and is not a legal DSP++ version file.\n" ;
		HelpOut << "Current state saved in file `" << TempFileName <<
			"'.\n" ;
		DspExecState->InformationComplete();
		return ;
	}
/*  // now using rename no deletion needed
 *	if (unlink(TempFileName)) {
 *			*Output + OutputCppHelp <<
 *				"Cannot delete temporary file `" << TempFileName << "'.\n" ;
 *		DspExecState->InformationComplete();
 *	}
 */
}

const char * current_delete_class = 0 ;

void InteractiveGlobal::DeleteAll()
{
	// LogOut << "InteractiveGlobal::DeleteAll() exit\n" ;
	// clear all nets
	InteractiveEntity * TheEntity;
	InteractiveEntityIterator Next(*TheNets);
	while (TheEntity=Next()) TheEntity->ClearNets();
	// LogOut << "InteractiveGlobal::DeleteAll() nets cleared\n" ;
	for (InteractiveEntityList ** Ptr = AllEntities; *Ptr; Ptr++) 
		(*Ptr)->DeleteAll();
	// LogOut << "InteractiveGlobal::DeleteAll() exit\n" ;
}

void InteractiveEntityList::DeleteAll()
{
/*
 *	LogOut << "InteractiveEntityList::DeleteAll() for base " <<
 *		GetBaseClassName() << "\n" ;
 */
	InteractiveEntity * TheEntity;
	while (TheEntity=Get()) {
/*
 *		LogOut << "DeleteAll for class " << TheEntity->GetClassName()
 *			<< "\n" ;
 */
		TheEntity->DeleteAll();
	}
}

int InteractiveEntityList::SaveState(OutTokens& Out, CppListCmds Cmd) 
{
	// LogOut << "InteractiveEntityList::SaveState\n" ;
	// LogOut << "base class is `" << BaseClassName << "'\n" ;
	InteractiveEntityIterator Next(*this) ;
	InteractiveEntity * Ent ;
	int Ok = 1 ;
	while (Ent=Next()) {
		// LogOut << "Save state for class `" << Ent->GetClassName() << "'\n" ;
		int Err = Ent->SaveState(Out,Cmd);
		Ok &= Err ;
	}
	return Ok ;
}
	
void InteractiveEntity::ClearNets()
{
	// LogOut << "InteractiveEntity::ClearNets for " << GetClassName() << "\n" ;
/*
 *	LogOut << "Deleting Interactive Entities - " <<
 *		GetClassName() << "\n" ;
 */
	if (GetDerivedEntity()) {
		GetDerivedEntity()->ClearNets();
	}
	if (GetBrotherEntity()) {
		GetBrotherEntity()->ClearNets();
	}
	UserEntity * Ent ;
	EntityListIterator Next(*EntityInstances) ;
	while (Ent=Next()) {
		if (!IsClassMember("ProcessNet")) {
			continue ;
		}
		((ProcessNet *) Ent)->ClearActiveNetwork();
	}
}
void InteractiveEntity::DeleteAll()
{
/*
 *	LogOut<<"InteractiveEntity::DeleteAll() for "<<GetClassName() << "\n" ;
 *	LogOut << "Deleting Interactive Entities - " <<
 *		GetClassName() << "\n" ;
 */
	if (GetDerivedEntity()) {
		GetDerivedEntity()->DeleteAll();
	}
	if (GetBrotherEntity()) {
		GetBrotherEntity()->DeleteAll();
	}
	UserEntity * Ent ;
	while (Ent=EntityInstances->Get()) {
		// LogOut << "InteractiveEntity::DeleteAll `"<<Ent->GetName() << "'\n" ;
		delete Ent;
	}
}


int InteractiveEntity::SaveState(OutTokens& Out, CppListCmds Cmd)
{
	EntityListIterator Next(*EntityInstances) ;
	UserEntity * Ent ;
	int Ok = 1 ;
	while (Ent=Next()) {
		if (Ent->IsUnusedDefault()) continue ;
		if (Cmd == CppListCtor) if (!Ent->IsDeleteable()) continue ;
		int Err = Ent->SaveState(Out,Cmd);
		Ok &= Err ;
	}
	return Ok ;
}


int InteractiveEntity::CppList(OutTokens& Out, CppListCmds Cmd,
	UserEntity * Object)
{
	if (!Object) DbgError("InteractiveEntity::CppList","null object");
	// LogOut << "Listing " << Object->GetName() << "\n" ;
	int Return = 1;
	int Error ;
	if (GetParameterArray()) {
		Error = GetParameterArray()->CppListDec(Out,Cmd,Object) ;
		// LogOut << "Error = " << Error << "\n" ;
		Return &= Error ;
	}
	DfNode * TheTargetNode = 0 ;
	if (Cmd == CppListTargetCtor) if (IsClassMember("DfNode")) 
		TheTargetNode = (DfNode *) Object ;
	if (TheTargetNode) TheTargetNode->EmitNodeSpecificInit(Out);
	Out.NextFillOut(GetClassName());
	Out.NextFillOut(Object->GetName());
	Out.NextConcat("(");
	Out.NextDblQuoteOut(Object->GetName());
	// LogOut << "Started listing\n" ;
	if (GetParameterArray()) {
		Object->Describe(Out,ListSetParameterValues);
		Error = GetParameterArray()->CppList(Out,Cmd);
		// LogOut << "Error = " << Error << "\n" ;
		Return &=Error ;
	}
	if (TheTargetNode) { // Only set for Target ctor
		Out.NextConcat(", ") ;
		if (TheTargetNode->GetIn()) {
			Out.NextConcatToken(Object->GetName());
			Out.NextOutToken(InputLinksSuffix);
		} else Out.NextOut("0") ;

		Out.NextConcat(", ") ;
		if (TheTargetNode->GetOut()) {
			Out.NextConcatToken(Object->GetName());
			Out.NextOutToken(OutputLinksSuffix);
		} else Out.NextOut("0") ;
		Out.NextConcat(", ") ;

		TargetNodeParameters * Parameters =
			TheTargetNode->GetTargetParameters() ;
		if (Parameters) if (Parameters->GetInitSize()
			|| Parameters->GetExecuteSize()) {
			Out.NextConcatToken(Object->GetName());
			Out.NextOutToken(ExecutionSequenceSuffix);
		} else Out.NextOut("0");
		Out.NextConcat(", ") ;

		Out.NextOut(ExecuteTypeName(TheTargetNode->GetExecuteType()));
		Out.NextConcat(", ") ;
		Out.NextOut(TheTargetNode->GetNodeDelay());
		TheTargetNode->EmitNodeSpecificCtorParameters(Out);
	}
	Out.NextConcat(");");
	Out.NewLine();
	return Return ;
	
}

