/*  mktarget.C   */
/*  Copyright 1990 Mountain Math Software  */
/*  All Rights Reserved                    */

/* mktarget.C - create topology code for target port */
#include <stream.h>
#include <fstream.h>
#include "mktarget.h"
#include "yacintfc.h"
#include "intfc.h"
#include "network.h"
#include "cgidbg.h"
#include "tardb.h"
#include "array.h"
#include "mkstr.h"
#include "travparm.h"
#include "specopt.h"
#include "shrdary.h"
#include "shrbuf.h"
#include "copyright.h"

ofstream& CreateTargetFile(const char * Directory, const char * Name)
{
 	char * FileName = Concatenate(Directory,"/",Name);
	ofstream * Out = new ofstream(FileName);
	if (!Out->good()) State.Error(
		"cannot create target network file \n`",
		FileName, "'");
	else {
		AddCopyright& add = AddCopyright::add_copyright();
        	add.write_short(*Out,Name,AddCopyright::default_user_flag,
            	AddCopyright::created_by);
	}
	// LogOut << "Created file `" << FileName << "'.\n" ;
	delete FileName ;
	return *Out ;
}

 //	ofstream& Out = CreateTargetFile(Directory,"topology.h");
 //	ofstream& HeadOut = CreateTargetFile(Directory,"nodehds.h");
 //	ofstream& NodeOut = CreateTargetFile(Directory,"nodlst.h");

EmitTargetCode::EmitTargetCode(const char * out_name, const char * head_name,
	const char * nodes_name,ProcessNet& net, const char * dir_name,
	const char * state_name, SharedArray * SharedArrays ):
	Net(net),
	Out(CreateTargetFile(dir_name,out_name)),
	NodeList(CreateTargetFile(dir_name,nodes_name)),
	HeadOut(CreateTargetFile(dir_name,head_name)),
	OutName(out_name),
	HeadName(head_name),
	NodesName(nodes_name),
	StateName(state_name),
	GoodState(1),
	OutTok(*new OutTokens(&Out,0,""," ","\t")),
	TheSharedArrays(SharedArrays),
	Object(* new TraverseObject(OutTok,"writing the target code",HeadOut,
		new TraverseParameters(*this)))
{
	// LogOut << "EmitTargetCode::EmitTargetCode\n" ;
	// LogOut << "TheSharedArrays = " << (void *) TheSharedArrays << "\n" ;
	if (!&Out || !&NodeList || !&HeadOut) {
		SetBadState();
		return ;
	}
	OutTok.SetSpecialOptions(new SpecialOptions(Object));
	// LogOut << "EmitTargetCode\n" ;
	char * TargetFileBaseName = RemoveSuffix(head_name,".cxx");
	char * FileName = Concatenate(TargetFileBaseName,".h");
	char * dir = GetLowestDirectory(dir_name) ;
	if (dir) {
		char * d = Concatenate(dir_name,"/");
		delete dir ;
		dir = d ;
	} else dir = "" ;
	ofstream& StateHeader = CreateTargetFile(dir_name,FileName);
	// HeadOut << "#include \"" << dir << TargetFileBaseName << ".h\"\n\n" ;
	HeadOut << "#include \"" << TargetFileBaseName << ".h\"\n\n" ;

	Out << "#include \"ObjProUsr/buffer.h\"\n\n" ;
	Out << "#include \"ObjProDSPcom/tarnod.h\"\n\n" ;
	if (TheSharedArrays) Out << "#include \"" << dir << 
		TheSharedArrays->GetHeaderName() << "\"\n\n" ;
	Out << "#include \"" << GetNodesName() << "\"\n\n" ;

	TheSharedBuffer.declare_name(Out);
	Out << "NetworkStateControl * TheNetworkReferenceFor_" <<
		Net.GetName() << ";\n\n";

	// LogOut << "CallCreateStaticExecutionTables\n" ;
	Net.CreateStaticExecutionTables(Object);
	// LogOut << "CallCreateStaticExecutionTables back\n" ;
	if (State.IsError()) goto CleanUp ;
	

	// Clear flags. These are used to insure an object is not emitted twice.
	ArrayDataIndexBase = ArrayDataIndex;
	// LogOut << "SaveState\n" ;
	AllEntityLists->SaveState(OutTok,CppClearDecFlag);
	// LogOut << "ClearAlreadyOutput\n" ;
	TargetDataBase->ClearAlreadyOutput();
	if (State.IsError()) goto CleanUp ;

	// LogOut << "in WriteTargetState\n" ;
	WriteTargetState();
	// LogOut << "did WriteTargetState\n" ;
	if (State.IsError()) goto CleanUp  ;

	WriteKernelNodes();
	// LogOut << "did WriteKernelNodes\n" ;
	AllEntityLists->SaveState(OutTok,CppClearDecFlag);
	// LogOut << "did SaveState\n" ;
	if (State.IsError()) goto CleanUp  ;

	Net.EmitThreadTable(Object,StateName);
	// LogOut << "did EmitThreadTable\n" ;
	delete TargetFileBaseName ;
	// LogOut << "did delete TargetFileBaseName\n" ;
	if (!&StateHeader) {
		State.Error("Cannot create file `",dir_name, "/",
			FileName ,"'");
		delete FileName ;
		goto CleanUp ;
	}
	StateHeader << "extern class ExecuteState " << StateName << ";\n" ;
	TheSharedBuffer.declare_space(Out);
	*Output + OutputCppHelp << "The total buffer space used is " <<
			TheSharedBuffer.GetMaxSize() << ".\n" ;
	delete FileName ;
	delete (ofstream *) &StateHeader ;
CleanUp:
	if (State.IsError()) SetBadState();
	Net.ClearTargetParameters(Object);
	// LogOut << "EmitTargetCode Exit\n" ;
}

EmitTargetCode::~EmitTargetCode()
{
	delete (TraverseObject *) &Object ;
	delete (OutTokens *) &OutTok ;
	delete (ofstream *) &Out;
	delete (ofstream *) &NodeList ;
	delete (ofstream *) &HeadOut ;
}

void EmitTargetCode::WriteKernelNodes()
{
/*
 *	Note some interactive nodes will not be part of the
 *	topology.
 *
 *	Other nodes will have completely different code that may
 *	be target dependent.
 *
 *	All topology changes i. e. node deletions are performed here.
 *	All node translations whether target dependent or not are
 *	performed in the target code generator.
 */
	Net.WriteKernelNodes(Object);
	
}

void EmitTargetCode::WriteTargetState()
{
	Net.WriteTargetState(Object);
}



