/*  member.c   */
/*  Copyright 1989 Mountain Math Software  */
/*  All Rights Reserved                    */
#include <stream.h>
#include <fstream.h>
#include "fileios.h"
#include <string.h>
#include "debug.h"
#include "text2.h"
#include "domknode.h"
#include "mknodey.h"
#include "mknodelx.h"
#include "nodeparm.h"
#include "member.h"
#include "outtok.h"
#include "textfrag.h"
#include "texutil.h"

void CheckMembers(TextFragmentList * Text)
{
	TextFragmentListIterator Next(*Text);
	TextFragment * Fragment ;
	while (Fragment = Next()) if (Fragment->Line < 0) {
		const char * String = Fragment->Text ;
		if (!TheMemberFunctions->IsFunctionName(String))
		    if (!TheMemberFunctions->IsParameterName(String))
			TheNodeCtor->IsNodeParameterName(String) ;
	}
}



struct RetType {
	const char * Return ;
	const char ** AliasValues ;
};
const char * DecIntObj[] = { "int","int16","int32","long",0} ;
const char * DecFloatObj[] = {"double", "float",0} ;
const char * DecStringObj[] = {"char *",0} ;
const char * DecComplexObj[] = {"complex",0} ;
const char * DecMachWordObj[] = {"MachWord",0} ;
const char * DecAccMachWordObj[] = {"AccMachWord",0} ;
const char * DecCxMachWordObj[] = {"CxMachWord",0} ;
const char * DecCxAccMachWordObj[] = {"CxAccMachWord",0} ;

static RetType ReturnTypes[] = {
	{"DecInt", DecIntObj},
	{"DecFloat", DecFloatObj},
	{"DecString", DecStringObj},
	{"DecComplex", DecComplexObj},
	{"DecMachWord", DecMachWordObj},
	{"DecAccMachWord", DecAccMachWordObj},
	{"DecCxMachWord", DecCxMachWordObj},
	{"DecCxAccMachWord", DecCxAccMachWordObj},
	{"DecEnt",0}
};

MemberFunctionList * TheMemberFunctions = 0 ;

static const char * MapCallReturnType(const char * Type)
{
	const char ** Sptr ;
	for (RetType * Ptr = ReturnTypes ; Sptr=Ptr->AliasValues; Ptr++)
		while (*Sptr) if (!strcmp(*Sptr++,Type)) return Ptr->Return ;
	return Ptr->Return ;
}

static void EmitParArrayName(MofStream& Out, const char * NodeName)
{
	Out << NodeName << "ParArray" ;
}

char * MakeParameterFunctionName(const char * BaseName)
{
	return MakeCompoundName(NodeName,"_",BaseName,"_Check");
}

enum CheckDefinesPlace {CheckDefineDefine, CheckDefineUndefine};

static void EmitCheckDefines(MofStream& Out, const char *ParmName,
	CompoundList * names, CheckDefinesPlace Place, int Type)
{
		switch (Place) {
case CheckDefineDefine:
		Out << "#define " << ParmName << " (This."
			<< GetOneParType(Type) << "P->CurrentValue)\n" ;
		break ;
case CheckDefineUndefine:
		Out << "#undef " << ParmName << "\n" ;
		break ;
default:
		DbgError("EmitCheckDefines","bad Place");
	}
		
	if (!names) return ;
	CompoundListIterator Next(*names);
	Compound * Elt ;
	for (int i = 0 ; Elt = Next(); i++) {
		if (Elt->Type != TypeName) DbgError("EmitCheckDefines",
			"bad type");
		const char * Name = Elt->Item.Str ;
		if (!strcmp(Name,ParmName)) continue ;
		switch (Place) {
case CheckDefineDefine:
			Out << "#define " << Name << " (One[" << i << "]->"
				<< GetOneParType(Type) << "P->CurrentValue)\n" ;
			break ;
case CheckDefineUndefine:
			Out << "#undef " << Name << "\n" ;
			break ;
default:
			DbgError("EmitCheckDefines","bad Place");
		}
		
	}
}

MemberFunctionList::~MemberFunctionList()
{
	Clear();
}

int MemberFunction::IsParameterName(const char * Name)
{
	if (!Parameters) return 0;
	NodeParameterListIterator Next(*Parameters) ;
	NodeParameter * Param ;
	while (Param=Next()) if (!strcmp(Param->Name,Name)) return 1;
	return 0;
}

int MemberFunction::IsFunctionName(const char * TestName)
{
	return !strcmp(Name,TestName);
}

void MemberFunction::EmitSetNodeVariables(MofStream& Out)
{
	NodeParameterListIterator Next(*Parameters);
	NodeParameter * Param;
	int index = 1;
	for (int count = 1; Param = Next() ; count++) {
		if (Param->IsChangeable()) {
			Out << "\tvoid Set" << Param->Name <<
				"(" << WhatTypeString(Param) <<
				" " << Param->Name << ") { " << Param->Name <<
				"_" << index << " = " << Param->Name << "; parameter_changed(); }\n" ;
		}
		index++ ;
		if (Param->IsArray()) index++ ;
	}
}

void MemberFunction::EmitMemberFunc(MofStream& FileOut)
{
	EmitCtorFunc(FileOut,0);
}


void MemberFunction::EmitCtorFunc(MofStream& FileOut,int CtorFlag)
{
	// cout << "CtorFlag = " << CtorFlag << "\n" ;
	if (Type) if (*Type) FileOut << Type << " ";
	FileOut << Name << " (" ;
	if (CtorFlag) FileOut << "const char * Name" ;
	NodeParameter * Param ;
	NodeParameterListIterator Next(*Parameters);
	int CharCount = strlen(Name) + 18 ;
	int FirstTime = !CtorFlag ;
	while (Param = Next()) {
		char Buf[80] ;
		const char * Type = WhatTypeString(Param) ;
		int LengthType = strlen(Type) ;
		const char * Nm = Param->Name ;
		int State = 0 ;
		for(;;) { // Loop is for double parameters associated
			// with an array
			if (!FirstTime) FileOut << ", " ;
			FirstTime = 0;
			int Increment = 2 + strlen(Type) + strlen(Nm) ;
			CharCount += Increment ;
			if (CharCount > 75) {
				CharCount = Increment + 14 ;
				FileOut << "\n		" ;
			}
			FileOut << Type << Nm ;
			if (State) {
				delete (void *) Nm;
				break ;
			}
			if (!Param->Size) break ;
			State = 1;
			Type = strcpy(Buf,"int32 ");
			Nm = MakeCompoundName(Param->Name,"_Length");
		}
	}
	if (CtorFlag) {
		FileOut.PushFirstFileSelect(BaseStreamBuf::Off);
		FileOut <<
		  ",\n\t\tDfNodeInLink* in_links, DfNodeOutLink* out_links," <<
		  "\n\t\tint ** exec_seq,  NodeExecuteType exec_type," <<
		  "\n\t\tint delay" ;
		EmitStaticInitCtorParams(FileOut) ;
		if (NetworkRefFlag) FileOut <<
			",\n\t\tNetworkStateControl ** network_ref" ;
		FileOut.PopFirstFileSelect();
	}
	FileOut << ")" ;	
}

static const char * WhatTypeStringCtor(NodeParameter * Parm)
{
	const char * BaseType = WhatTypeString(Parm);
	int Length = strlen(BaseType) ;
	if (BaseType[Length-1] != '&') return BaseType;
	const BufSize = 128;
	static char Buf[BufSize+1];
	if (Length > BufSize) DbgError("WhatTypeStringCtor",
		"class name too long");
	strcpy(Buf,BaseType);
	Buf[Length-1] = '*' ;
	return Buf ;
}

void MemberFunction::EmitCtor(MofStream& Out)
{
	NodeParameter * Param ;
	NodeParameterListIterator Next(*Parameters);
	int ParamCount = 0 ;
	while (Param = Next()) {
		Out << "\t" << WhatTypeStringCtor(Param) << " " << Param->Name
			<< "_" << ++ParamCount << ";\n" ;
		if (Param->Size) Out << "\tint32 " << Param->Name <<
				"_Length_" << ++ParamCount << ";\n" ;
	}
	Out << "public:\n	" ;
	TheNodeCtor->EmitCtorFunc(Out) ;
	Out << ";\n\tvirtual ~" << Name << "();\n" ;
	NodeParameterListIterator NewNext(*Parameters);
	ParamCount = 0;	
	while (Param = NewNext()) {
		ParamCount++ ;
		Out << "\t" << WhatTypeStringCtor(Param) << "Get" <<
			Param->Name << "() const {return " <<
			Param->Name << "_" << ParamCount <<";}\n" ;
		if (Param->Size) {
			Out << "\tint32 Get" << Param->Name <<
				"_Length() const {return " << Param->Name <<
				"_Length_" << ++ParamCount << ";}\n" ;
		}
	}
}

int IsReference(const char * Type)
{
	if (!Type) return 0;
	int Length = strlen(Type);
	return Type[Length-1] == '&' ;
}

void MemberFunction::EmitAssignCtorParam(MofStream& Out)
{
	NodeParameterListIterator Next(*Parameters);
	NodeParameter * AParameter ;
	int i = 0 ;
	while (AParameter = Next()) {
		Out << ",\n\t" << AParameter->Name  << "_" << ++i << "(" ;
		if (IsReference(AParameter->ClassType)) Out << "&" ;
		Out << AParameter->Name << ")" ;
		if (AParameter->Size) {
			Out << ",\n\t" << AParameter->Name << "_Length_" << ++i
				<< "("<< AParameter->Name << "_Length)" ;
		}
	}
}

void MemberFunction::EmitNodeParameterDescriptions(MofStream& Out)
{
	ConstStringList AlreadyEmitted;
	Out << "\t\tOut.NewLine();\n";
	if (is_constructor()) Out << "\t\tMake" ;
	Out << Name << "(Out,EntityReqDescribeFull,*IntEnt" ;
	if (is_constructor()) Out << Name ;
	else Out << Type ;
	Out << ", (ArithType::ArithCapabilities) TheArithType);\n" ;

	Out << "\t\tOut.NewLine();\n";
	if (!AnyParameters())
		Out << "\t\tOut.NextFillOut(\"There are no parameters for the constructor of this class.\");\n" ;
	else {
		NodeParameterListIterator Next(*Parameters);
		NodeParameter * Param ;
		while (Param = Next()) EmbeddedTextOut(Param->FullDescription, &Out,
			&AlreadyEmitted);
	}
	Out << "\t\tOut.NewLine();\n";
}

void MemberFunction::EmitSetNodeParameterValues(MofStream& Out)
{
	NodeParameterListIterator Next(*Parameters);
	NodeParameter * Param ;
	int Index=1;
	while (Param = Next()) Param->EmitSetNodeParameterValue(Out,Name,Index);
}

const char * DoEmitParameterList(MofStream& Out, const char * BaseName, int Type,
	ParameterFunction * Func, CheckFuncPlace Place)
{
	CompoundList * names = Func->NameList ;
	if (!names) return MakeName("0") ;
	const char * Return = MakeParameterFunctionName(BaseName);
	switch(Place) {
case CheckFuncExternal:
		Out << "static int32 " << Return <<
			"(CheckAction, OneParameter& This,\n" <<
			"\tOneParameter ** One, OutTokens * Out)\n{\n" ;
		EmitCheckDefines(Out,BaseName,names,CheckDefineDefine,Type);
		EmitCppCode(Func->Code);
		EmitCheckDefines(Out,BaseName,names,CheckDefineUndefine,Type);
		Out << "\n}\n\n" ;
		break ;
case CheckFuncHeader:
		Out << "\tstatic OneParameter * " << Return <<
			"_List[" << (names->Size()+1) << "] ;\n" ;
		Out << "\tstatic DoCheck" << TypePrefix(Type) << "Bound "
			<< Return << "_Struct = {\n\t\t" <<  Return <<  ", "
			<< Return << "_List" << "};\n\n" ;
		break ;
case CheckFuncAssign:
		{
		Compound * name ;
			CompoundListIterator Next(*names);
			int i = 0 ;
			while (name = Next()) {
			Out << "\t" << Return << "_List[" << i++ << "] = " ;
				TheNodeCtor->DoEmitParameterListElement(
					Out,name) ;
				Out << " ;\n" ;
			}
		}
		break ;
	}
	return Return ;
}

void DoEmitParamCheckFunc(MofStream& Out, int Type, const char * name,
	Compound * param, CheckFuncPlace Place)
{
	if (param->Type != TypeParamFunc) return ;
	// Define structure which references list of parameters
	ParameterFunction * Func = param->Item.ParamFunc ;
	const char * ListName = DoEmitParameterList(Out,
		name,Type,Func,Place);
	// Define subroutine
	// Define structure to be used in Data structure reference
	delete (void *) ListName ;
}




static void VoidValueObjectOut(MofStream& Out, int Type, const char * StrScaleFac,
	Compound * Value, const char * Name)
{
	Out << "\tstatic " ;
	if (IsVoidNumericType(Type)) Out << " Cast" ;
	Out << WhatTypeString(Type) << Name << " =\n\t\t" ;
	if (IsVoidNumericType(Type)) Out << "{" ;
	EmitScaledValue(Value,StrScaleFac,Type) ;
	if (IsVoidNumericType(Type)) Out << "}" ;
	Out << " ;\n\n" ;
}

void MemberFunction::EmitParamCheckFuncs(MofStream& Out, CheckFuncPlace Place)
{
	NodeParameter * NodeParam ;
	NodeParameterListIterator Next(*Parameters) ;
	while (NodeParam = Next()) NodeParam->EmitParamCheckFunc(Out,Place) ;
}

void MemberFunction::EmitCtorParameterChecks(MofStream& Out)
{
	NodeParameter * NodeParam ;
	NodeParameterListIterator Next(*Parameters) ;
	while (NodeParam = Next()) NodeParam->ParamOut(Out,"") ;
	Out << "\n" ;
}

void MemberFunction::EmitCtorParameterArray(MofStream& Out)
{
	Out << "\tstatic OneParameter " << NodeName <<
		"ParArray[] = {\n\t\t{\"Name\", 0, \"node name\", 0, 0, &"
		<< NodeName << "NameParam},\n" ;
	NodeParameter * NodeParam ;
	NodeParameterListIterator Next(*Parameters) ;
	while (NodeParam = Next()) NodeParam->ParamArrayEltOut(Out,Name) ;
	Out << "\t\t{0}\n\t};\n\n" ;
}

static const char * NameTable[][2] = {
	{">>","RightShift_Op"},
	{"<<","LeftShift_Op"},
	{"*","Multiply_Op"},
	{"/","Divide_Op"},
	{"+","Add_Op"},
	{"-","Subtract_Op"},
	{"&","And_Op"},
	{"|","And_Op"},
	{">","GreaterThan_Op"},
	{"<","LessThan_Op"},
	{"=","Equal_Op"},
	{">=","GreaterEqual_Op"},
	{"<=","LessEqual_Op"},
	{"==","LogicalEqual_Op"},
	{"&&","LogicalAnd_Op"},
	{"||","LogicalOr_Op"},
	{0,0}
};
	

static const char *OperTable(const char * Oper)
{
	for (int i = 0; NameTable[i][0];i++) 
		if (!strcmp(NameTable[i][0],Oper)) return
			NameTable[i][1];
	DbgError("OperTable unknown operator",Oper);
	return 0;
}

const char *OperConvert(const char * Name)
{
	const char * Oper  = "operator" ;
	int OperLength = strlen(Oper);
	if (strncmp(Name,Oper,OperLength)) return Name ;
	return OperTable(Name+OperLength) ;
}

void MemberFunction::EmitMemberFunction(MofStream& Out)
{
	Out << "static ValueType * " << OperConvert(Name) << 
		"(OutTokens& Out,EntityReq Request,\n\t\tUserParameters * Param,"
		<< "UserEntity *This) \n{" <<

		"\n\tswitch (Request) {\n" <<
			"case EntityReqDescribe:\n" <<
			"case EntityReqDescribeFull:\n" ;
	EmbeddedTextOut(FullDescription, &Out);
	Out << "\t\tOut.NewLine();\n";
	CheckMembers(FullDescription) ;
	Out << "\n\tbreak ;\n" <<
			"case EntityReqCall:\n\t\t{" ;
	NodeParameterListIterator Next(*Parameters);
	NodeParameter * Param ;
	while (Param = Next()) Param->EmitCallGetParameter(Out);

	int VoidType = !strcmp(Type,"void");

	if (!VoidType) {
		Out << "\n\t\tValueType * ValueTypeReturn = new ValueType("
		<< MapCallReturnType(Type) << ",(UserEntity *)" ;
		if (Type[strlen(Type)-1] == '&') Out << "&" ;
			// Convert referennce to pointer if needed
	} else Out << "\n\t\t" ;
	Out << "((" << NodeName << " * )" ;
	Out << "This)->" << Name << "(\n\t\t" ;
	NodeParameterListIterator Next2(*Parameters);
	int FirstTime =1 ;
	while (Param = Next2()) {
		if (!FirstTime) Out << ", " ;
		FirstTime = 0;
		Out << Param->Name ;
	}
	if (!VoidType) Out << ")" ;
	Out << ");" ;
	if (!VoidType) Out << "\n\t\treturn ValueTypeReturn;\n" ;
	Out << "\t\t}\n\t}\n\treturn 0;\n}\n\n" ;
}

void MemberFunction::EmitSetVariables(MofStream& Out)
{
	NodeParameterListIterator Next(*Parameters);
	NodeParameter * Param ;
	while (Param=Next()) if (Param->IsChangeable()) {
		Out << "static ValueType * Set" << Param->Name << 
		"(OutTokens&,EntityReq Request,\n\t\tUserParameters * Param,"
		<< "UserEntity *This) \n{" <<

		"\n\tswitch (Request) {\n" <<
			"case EntityReqDescribe:\n\tbreak ;\n" <<
			"case EntityReqDescribeFull:\n\tbreak ;\n" <<
			"case EntityReqCall:\n\t\t{" ;

		Out << "\t\t// Call procedure\n\t\t" ;
/*
 *		Out << WhatTypeString(Param) << Param->Name <<
 *			" = Param->Get" ;
 *		Out << WhatTypeString(Param->Type->Type, DataDecPrefixType)
 *			<< "ParameterValue(\"" << Param->Name ;
 *		Out << "\");\n";
 */
		Param->EmitCallGetParameter(Out);

		Out << "\t\t((" << NodeName << " *) This)->"
			<< "Set" << Param->Name << "(" << Param->Name << ");\n"
			<< "\t\treturn 0 ;\n\t}\n\t}\n\treturn 0;\n}\n\n" ;
	}
}

void EmitEntry(MofStream& Out, const char * Name, const char * NodeName,
const char * Pre)
{
	if (!Pre) Pre = "" ;
	Out << "\t" << NodeName << "Members[ii++] = new ValueType("
		<< "DecProcedure, " << Pre << "MemberProc" <<
		OperConvert(Name) << ") ;\n" ;

}



void MemberFunction::EmitMemberEntry(MofStream& Out, const char * NodeName)
{
	EmitEntry(Out,Name,NodeName,0);
}


void MemberFunction::EmitInteractiveCompleteStructures(MofStream& Out,
	MemberFunctionList * Members,const char * Prefix)
{
	NodeParameterListIterator Next(*Parameters);
	NodeParameter * Param ;
	Out << "\tint ii = 0 ;\n" ;
	while (Param=Next()) if (Param->IsChangeable())
		Param->EmitMemberEntry(Out, NodeName, Prefix);
	MemberFunction * Member ;
	MemberFunctionListIterator MemNext(*Members);
	while (Member = MemNext()) Member->EmitMemberEntry(Out,NodeName);
	Out << "\t" << NodeName << "Members[ii++] = 0 ;\n" ;
}


void MemberFunction::EmitInteractiveInterface(MofStream& Out,
	MemberFunctionList * Members)
{
	int AnyChangeable = Parameters->AnyChangeable() ;
	int AnyMembers = Members->Size() > 0 ;
	if (!AnyMembers && !AnyChangeable) return ;
	int Size = 0;
	if (AnyChangeable) {
		NodeParameterListIterator Next(*Parameters);
		NodeParameter * Param ;
		while (Param=Next()) if (Param->IsChangeable()) {
			Size++ ;
			Param->EmitInteractiveGetValue(Out,"Set");
		}
	}
	if (AnyMembers) Members->EmitInteractiveInterface(Out) ;
	Size += Members->Size();
	Out << "static ValueType * " << NodeName << "Members[" << Size+1
		<< "] ;\n" ;

	EmitInteractiveCompleteStructures(Out,Members,"Set");

}

void MemberFunction::CheckForArrayExt(MofStream& Out, MofStream& Hout)
{
	// Declare data for default array parameters external
	NodeParameter * Param ;
	NodeParameterListIterator Next(*Parameters);
	while (Param = Next()) if (Param->Size) {
		char * DefaultName = MakeDefaultArrayName ( Name,
			Param->Name);
		Param->DefaultArrayOut(Out,Hout,DefaultName);
		// values are output earler so they can be external
		delete DefaultName ;
	}
}


void MemberFunction::EmitGetParameters(MofStream& Out, int CtorFlag)
{
	if (CtorFlag) Out <<
	"\t\tconst char * Name = IntNode.GetStringParameterValue(\"Name\");\n" ;
	NodeParameterListIterator Next(*Parameters);
	NodeParameter * Param ;
	while (Param = Next()) Param->EmitGetParameter(Out);
}

void MemberFunction::EmitDecInteractiveEntity(MofStream& Out,
		MemberFunctionList * Members)
{
	Out << "\t" << Name  <<
		"NodeList = new EntityList;\n\tIntEnt" << Name <<
		" = new InteractiveEntity(\"" << Name << "\", "  <<
		Name << "NodeList,\n\t\t" ;
	if (BaseSwitch) Out << "0" ;
	else Out << "Make" << Name ;
	Out << ", " << InteractiveEntityListName << ", \""  <<
		HeaderName << "\",\n\t\t" ;
	if (Parameters->AnyChangeable() || Members->Size()) 
		Out << Name << "Members" ;
	else Out << "0" ;
	Out << ", \"" << GetBaseClassName() << "\");\n" ;
}

void MemberFunction::IsNodeParameterName(const char * TestName)
{
	if (!strcmp(TestName,NodeName)) return ;
	if (!strcmp(TestName,"Name")) return ;
	NodeParameterListIterator Next(*Parameters);
	NodeParameter * Param ;
	while (Param = Next()) if (!strcmp(TestName,Param->Name)) return ;
	cerr << "Warning: embedded name `$" << TestName <<
		"' is not a parameter name for node `" << Name <<
		"'.\n" ;
}

void MemberFunction::DoEmitParameterListElement(MofStream& Out, Compound * name)
{
	if (name->Type != TypeName) DbgError("DoEmitParameterListElement",
		"bad type");
	const char * Name = name->Item.Str ;
	NodeParameter * Test ;
	NodeParameterListIterator Next(*Parameters);
	int ParCount = 0 ;
	while (Test = Next()) {
		ParCount++ ;
		if (!strcmp(Test->Name,Name)) {
			Out << "&" ;
			EmitParArrayName(Out,Name);
			Out <<  "[" << ParCount << "]" ;
			return ;
		}
	}
}




void MemberFunction::EmitInteractiveInterface(MofStream& Out)
{
	NodeParameterListIterator Next(*Parameters);
	NodeParameter * Param ;
	while (Param=Next()) Param->ParamOut(Out,Name);
	Out << "\tstatic OneParameter " << OperConvert(Name) << NodeName
		<< "List[] = {\n" ;
	NodeParameterListIterator Next2(*Parameters);
	while (Param=Next2()) Param->EmitInteractiveMemberParameter(Out,
		OperConvert(Name));
	Out << "\t\t{0}\n\t};\n" ;

	Out << "\tUserParameters * " << OperConvert(Name) << "MemberParam" <<
		" = new UserParameters\n\t\t(" << 
		OperConvert(Name) << NodeName << "List);\n\n" ;

	Out << "\tProcedure * " << "MemberProc" << OperConvert(Name) <<
		" = new Procedure(\"" << Name
		<< "\", " << OperConvert(Name) 
		<< ",\n\t\t" << OperConvert(Name) << "MemberParam"
		<< ", \"" << Type << "\", 0, " ;
	if (HelpLine) EmitQuotedHelpLine(Out,HelpLine) ;
	else Out << "0" ;
	Out << ");\n" ;

}

void MemberFunction::EmitMemberParmCheckFuncs()
{
}

void MemberFunction::EmitInteractiveFunctions()
{
}

char * MakeDefaultArrayName ( const char * Node, const char * Param)
{
	return MakeCompoundName ( Node, Param, "DefaultArray");
}


int MemberFunctionList::IsParameterName(const char * Name)
{
	MemberFunctionListIterator Next(*this);
	MemberFunction * Member ;
	while (Member = Next()) if (Member->IsParameterName(Name)) return 1;
	return 0;
}

int MemberFunctionList::IsFunctionName(const char * Name)
{
	MemberFunctionListIterator Next(*this);
	MemberFunction * Member ;
	while (Member = Next()) if (Member->IsFunctionName(Name)) return 1;
	return 0;
}

void MemberFunctionList::EmitMemberDeclarations(MofStream& Out)
{
	MemberFunctionListIterator Next(*this) ;
	MemberFunction * Member ;
	while (Member = Next()) {
		Out << "\t" ;
		Member->EmitMemberFunc(Out);
		Out << ";\n" ;
	}
}


void MemberFunctionList::EmitInteractiveInterface(MofStream& Out)
{
	MemberFunctionListIterator Next(*this) ;
	MemberFunction * Member ;
	while (Member = Next()) {
		Member->EmitInteractiveInterface(Out);
	}
}

void MemberFunctionList::EmitMemberFunctions(MofStream& Out)
{
	MemberFunctionListIterator Next(*this) ;
	MemberFunction * Member ;
	while (Member = Next()) Member->EmitMemberFunction(Out);
}

void MemberFunction::EmitCheckLegalFunctions(MofStream& Out,
	const char * NodeName)
{
	NodeParameterListIterator Next(*Parameters);
	NodeParameter * Param ;
	while (Param = Next()) Param->EmitCheckFunctionDefiniton(Out,NodeName);
}

int MemberFunction::AnyParameters()
{
	if (!Parameters) return 0;
	if (!Parameters->Size()) return 0;
	return 1;
}

void MemberFunctionList::EmitMemberParmCheckFuncs()
{
}

void MemberFunctionList::EmitInteractiveFunctions()
{
}

void MemberFunction::BriefOutTeX(OutTokens& Out)
{
	Out.NextConcatToken("\\paragraph{");
	Out.NextTeXttOut(Name);
	Out.NextOutToken("}");
	Out.TeXIndexEntry(Name);
	Out.FlushLine();
	Out.NewLine();

	Out.NextOut("Synopsis:");
	HelpLine->OutTeXEndDot(Out);
	Out.NextFillOut("This function returns type");
	Out.NextTeXttOut(Type);
	Out.NextConcat(".");
	VSpace(Out);

	if (Parameters->Size()) {
		Out.NextFillOut("The parameters of this function are:");
		VSpace(Out);

		Parameters->BriefOutTeX(Out);
	} else Out.NextFillOut("This function has no parameters.\n");
	Out.NewLine();
	Out.NewLine();
}

void MemberFunction::OutTeX(OutTokens& Out)
{
	Out.NextConcatToken("\\subsubsection{");
	Out.NextTeXttOut(Name);
	Out.NextOutToken("}");
	Out.TeXIndexEntry(Name);
	Out.FlushLine();
	Out.NewLine();

	Out.NextOut("Synopsis:");
	HelpLine->OutTeXEndDot(Out);
	VSpace(Out).NextFillOut("This function returns type");
	Out.NextTeXttOut(Type);
	Out.NextConcat(".");
	
	FullDescription->OutTeX(VSpace(Out));
	VSpace(Out);

	if (Parameters->Size()) {
		Out.NextFillOut("The parameters of this function are:");

		Parameters->OutTeX(VSpace(Out));
	} else Out.NextFillOut("This function has no parameters.\n");
	Out.NewLine();
	Out.NewLine();
}


