aknlayoutcompiler/src/LayCdl2Inst.cpp
changeset 0 f58d6ec98e88
child 1 b700e12870ca
equal deleted inserted replaced
-1:000000000000 0:f58d6ec98e88
       
     1 /*
       
     2 * Copyright (c) 2002-2004 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // disable "identifier was truncated to '255' characters in the browser information" warning
       
    21 #pragma warning (disable:4786)
       
    22 
       
    23 #include "LayCdl2Inst.h"
       
    24 #include "LayoutCompilerErr.h"
       
    25 #include "LayoutParse.h"
       
    26 #include "CppWriter.h"
       
    27 #include "Lay2Cdl.h"
       
    28 #include <fstream>
       
    29 #include <algorithm>
       
    30 #include <iostream>
       
    31 #include "CodeGenConsts.h"
       
    32 using namespace std;
       
    33 using namespace CdlCompilerToolkit;
       
    34 
       
    35 typedef LayoutProcessArgsErr<LayoutAndCdlToCdlInstance> LayoutAndCdlToCdlInstanceArgsErr;
       
    36 
       
    37 
       
    38 class LayoutAndCdlToCdlInstanceChecker : public MCdlTkApiCheckObserver
       
    39 	{
       
    40 private:
       
    41 	void StartCheck();
       
    42 	void CheckComplete();
       
    43 	void ApiInBoth(const CCdlTkApi& aApi);
       
    44 	void ApiNotInLeft(const CCdlTkApi& aApi);
       
    45 	void ApiNotInRight(const CCdlTkApi& aApi);
       
    46 
       
    47 private:
       
    48 	int iNotInLeft;
       
    49 	int iNotInRight;
       
    50 	};
       
    51 
       
    52 
       
    53 void LayoutAndCdlToCdlInstanceChecker::StartCheck()
       
    54 	{
       
    55 	iNotInLeft = 0;
       
    56 	iNotInRight = 0;
       
    57 	}
       
    58 
       
    59 void LayoutAndCdlToCdlInstanceChecker::CheckComplete()
       
    60 	{
       
    61 	if (iNotInLeft)
       
    62 		cout << "Layout is partial implementation of interface" << endl;
       
    63 	if (iNotInRight)
       
    64 		throw CdlTkAssert("Layout interface check failed");
       
    65 	}
       
    66 
       
    67 void LayoutAndCdlToCdlInstanceChecker::ApiInBoth(const CCdlTkApi& /*aApi*/)
       
    68 	{
       
    69 	}
       
    70 
       
    71 void LayoutAndCdlToCdlInstanceChecker::ApiNotInLeft(const CCdlTkApi& /*aApi*/)
       
    72 	{
       
    73 	iNotInLeft++;
       
    74 	}
       
    75 
       
    76 void LayoutAndCdlToCdlInstanceChecker::ApiNotInRight(const CCdlTkApi& aApi)
       
    77 	{
       
    78 	iNotInRight++;
       
    79 	cerr << aApi.Name() << " not in interface" << endl;
       
    80 	}
       
    81 
       
    82 
       
    83 int LayoutAndCdlToCdlInstance::Process(const vector<string>& args)
       
    84 	{
       
    85 	if (args.size() < 5 || args.size()%2 == 0)
       
    86 		throw LayoutAndCdlToCdlInstanceArgsErr();
       
    87 
       
    88 	string cdlName = args[2];
       
    89 	CCdlTkCdlFileParser parser(cdlName);
       
    90 	auto_ptr<CCdlTkInterface> iface(parser.LoadAndParse(true));
       
    91 
       
    92 	LayoutAndCdlToCdlInstance process(*iface);
       
    93 
       
    94 	TLayout* base = NULL;
       
    95 	for (int arg = 3; arg < args.size(); arg += 2)
       
    96 		{
       
    97 		string layoutName = args[arg];
       
    98 		string instName = args[arg+1];
       
    99 		auto_ptr<TLayParseLayout> layoutParse = TLayParseLayout::Parse(layoutName);
       
   100 		auto_ptr<TLayout> layout(layoutParse.get());
       
   101 		layoutParse.release();
       
   102 		if (base)
       
   103 			{
       
   104 			auto_ptr<TLayout> newLayout(new TLayout(*base));
       
   105 			newLayout->Merge(TLayout::KMergeModeVariant, *layout);
       
   106 			layout = newLayout;
       
   107 			}
       
   108 		else
       
   109 			{
       
   110 			base = layout.get();
       
   111 			}
       
   112 		process.AddLayout(layout, instName);
       
   113 		}
       
   114 
       
   115 	process.WriteInstances();
       
   116 
       
   117 	return 0;
       
   118 	}
       
   119 
       
   120 void LayoutAndCdlToCdlInstance::ShowHelp(ostream& stream)
       
   121 	{
       
   122 	stream << "LayCdl2Inst <cdlName> (<layoutName> <instanceName>)+ " << endl;
       
   123 	stream << "  Creates CDL instances containing the layout data." << endl;
       
   124 	stream << "  All layout instances must conform to the CDL interface." << endl;
       
   125 	stream << "  If more than one layout is supplied, subsequent ones are treated as" << endl;
       
   126 	stream << "  variants of the first." << endl;
       
   127 	}
       
   128 
       
   129 void LayoutAndCdlToCdlInstance::CheckLayoutAgainstInterface(const TLayout& aLayout, const CCdlTkInterface& aIface)
       
   130 	{
       
   131 	auto_ptr<CCdlTkInterface> layIface = LayoutToCdl::LayoutToInterface(aLayout);
       
   132 	LayoutAndCdlToCdlInstanceChecker checker;
       
   133 	CCdlTkApiChecker check(*layIface, aIface, checker);
       
   134 	check.Process();
       
   135 	}
       
   136 
       
   137 LayoutAndCdlToCdlInstance::LayoutAndCdlToCdlInstance(CCdlTkInterface& aInterface)
       
   138 : iInterface(aInterface)
       
   139 	{
       
   140 	}
       
   141 
       
   142 LayoutAndCdlToCdlInstance::~LayoutAndCdlToCdlInstance()
       
   143 	{
       
   144 	for (CLayouts::iterator pLayout = iLayouts.begin(); pLayout != iLayouts.end(); ++pLayout)
       
   145 		delete *pLayout;
       
   146 	}
       
   147 
       
   148 void LayoutAndCdlToCdlInstance::AddLayout(auto_ptr<TLayout>& aLayout, const string& aInstName)
       
   149 	{
       
   150 	CLayoutToInst* base = NULL;
       
   151 	if (iLayouts.size())
       
   152 		base = iLayouts[0];
       
   153 	auto_ptr<CLayoutToInst> p(new CLayoutToInst(base, iInterface, aLayout, aInstName));
       
   154 	iLayouts.push_back(p.get());
       
   155 	p.release();
       
   156 	}
       
   157 
       
   158 void LayoutAndCdlToCdlInstance::WriteInstances()
       
   159 	{
       
   160 	CLayouts::iterator pLayout = iLayouts.begin();
       
   161 	CLayouts::iterator end = iLayouts.end();
       
   162 	
       
   163 	if (pLayout!=end)
       
   164 		(*pLayout)->Process();
       
   165 
       
   166 	for (; pLayout != end; ++pLayout)
       
   167 		{
       
   168 		CCdlTkWriteInstance writer((*pLayout)->Instance());
       
   169 		writer.Process();
       
   170 		}
       
   171 	}
       
   172 
       
   173 
       
   174 CLayoutToInst::CLayoutToInst(CLayoutToInst* aBase, CCdlTkInterface& aInterface, auto_ptr<TLayout>& aLayout, const string& aInstName)
       
   175 : iBase(aBase), iInterface(aInterface), iLayout(*aLayout), iInstName(aInstName)
       
   176 	{
       
   177 	iLayoutPtr = aLayout.get();
       
   178 	aLayout.release();
       
   179 
       
   180 	iInstance = new CCdlTkInstance(iInterface);
       
   181 	iInstance->SetName(aInstName);
       
   182 
       
   183 	string extraCpp("#include <aknlayout2datadef.h>\n");
       
   184 	extraCpp += string("#include \"") + CdlTkUtil::ToLower(aBase ? aBase->FwdDeclName() : FwdDeclName()) + "\"\n";
       
   185 	iInstance->SetExtraCpp(extraCpp);
       
   186 
       
   187 	for (TLayout::iterator pTab = iLayout.begin(); pTab != iLayout.end(); ++pTab)
       
   188 		{
       
   189 		AddTableToInstance(**pTab);
       
   190 		}
       
   191 	}
       
   192 
       
   193 CLayoutToInst::~CLayoutToInst()
       
   194 	{
       
   195 	delete iInstance;
       
   196 	delete iLayoutPtr;
       
   197 	}
       
   198 
       
   199 string CLayoutToInst::FwdDeclName()
       
   200 	{
       
   201 	if (iBase)
       
   202 		return iBase->FwdDeclName();
       
   203 	else
       
   204 		return iInstName + ".FwdDecl.h";
       
   205 	}
       
   206 
       
   207 void CLayoutToInst::Process()
       
   208 	{
       
   209 	string fileName(FwdDeclName());
       
   210 	string interfaceNsName = iInterface.NamespaceName();
       
   211 
       
   212 	ofstream stream;
       
   213 	CCdlTkFileCleanup tempFile;
       
   214 	CdlTkUtil::OpenTempOutput(stream, tempFile);
       
   215 
       
   216 	WriteHeaderGuardStart(fileName, stream);
       
   217 	stream << "namespace " << CdlTkUtil::ToCpp(iInstance->Name()) << endl;
       
   218 	stream << "{" << endl;
       
   219 
       
   220 	CCdlTkApiList& apiList = iInterface.ApiList();
       
   221 	for (CCdlTkApiList::iterator pApi = apiList.begin(); pApi != apiList.end(); ++pApi)
       
   222 		{
       
   223 		if ((*pApi)->IsFunc())
       
   224 			{
       
   225 			stream << "extern " << interfaceNsName << "::" << (*pApi)->AsFunc().ApiNameAsTypeName() << " " << (*pApi)->Name() << ";" << endl;
       
   226 			}
       
   227 		else
       
   228 			{
       
   229 			string typeExt = "Imp";
       
   230 			if ((*pApi)->ReturnType() == KTypeLayoutTableLimits)
       
   231 				typeExt = "";
       
   232 			stream << "extern " << (*pApi)->ReturnType() << typeExt << " const " << (*pApi)->Name() << ";" << endl;
       
   233 			}
       
   234 		}
       
   235 
       
   236 	stream << "}" << endl << endl;
       
   237 	WriteHeaderGuardEnd(fileName, stream);
       
   238 
       
   239 	stream.close();
       
   240 	CdlTkUtil::ExportFile(tempFile, CdlTkUtil::OutputPath() + fileName);
       
   241 	}
       
   242 
       
   243 CCdlTkInstance& CLayoutToInst::Instance()
       
   244 	{
       
   245 	return *iInstance;
       
   246 	}
       
   247 
       
   248 void CLayoutToInst::AddTableToInstance(TLayoutTable& aTable)
       
   249 	{
       
   250 	for (TLayoutTable::iterator pLine = aTable.begin(); pLine != aTable.end(); ++pLine)
       
   251 		{
       
   252 		TLayoutLine& line = **pLine;
       
   253 		if (line.iIsMergedIdentical)
       
   254 			{
       
   255 			string apiName = LayoutToCdl::LineApiName(line);
       
   256 			AddFwdRefToInstance(apiName, false);
       
   257 
       
   258 			string multilineApiName = KFuncMultiline + apiName;
       
   259 			if (aTable.iType == TLayoutTable::ETextTable &&
       
   260 				line["B"].size() > 1 &&
       
   261 				HasApi(multilineApiName))
       
   262 				{
       
   263 				AddFwdRefToInstance(multilineApiName, false);
       
   264 				}
       
   265 			}
       
   266 		else
       
   267 			{
       
   268 			if (aTable.iType == TLayoutTable::EWindowTable)
       
   269 				AddWindowLineToInstance(line);
       
   270 			else
       
   271 				AddTextLineToInstance(line);
       
   272 			}
       
   273 		}
       
   274 
       
   275 	int tableNum = 0;
       
   276 	for (TLayoutTable::TLayoutSubTables::const_iterator pSub = aTable.iSubTables.begin(); pSub != aTable.iSubTables.end(); ++pSub)
       
   277 		{
       
   278 		TLayoutTable::TLayoutSubTable& sub = **pSub;
       
   279 		if (sub.iIsMergedIdentical)
       
   280 			{
       
   281 			AddFwdRefToInstance(LayoutToCdl::TableApiName(aTable, sub, tableNum)+KFuncLimitsSuffix, false);
       
   282 			AddFwdRefToInstance(LayoutToCdl::TableApiName(aTable, sub, tableNum), false);
       
   283 			}
       
   284 		else
       
   285 			{
       
   286 			AddTableLimitsToInstance(aTable, sub, tableNum);
       
   287 			string tableType = KTypeTextLineLayout;
       
   288 			if (aTable.iType == TLayoutTable::EWindowTable)
       
   289 				tableType = KTypeWindowLineLayout;
       
   290 			AddSubTableToInstance(tableType, aTable, sub, tableNum);
       
   291 			}
       
   292 		tableNum++;
       
   293 		}
       
   294 	}
       
   295 
       
   296 void CLayoutToInst::AddWindowLineToInstance(TLayoutLine& aLine)
       
   297 	{
       
   298 	string apiName = LayoutToCdl::LineApiName(aLine);
       
   299 	if (!HasApi(apiName))
       
   300 		return;
       
   301 	CCdlTkImplementation& imp = FindImp(apiName);
       
   302 	SetFuncLine(imp, aLine, KTypeWindowLineLayout, KWindowOutputOrder, KWindowOutputOrderSize, "", "");
       
   303 	}
       
   304 
       
   305 const string KMultiLineTextLineExtra = "\
       
   306 \tline.iB = KB[0];\n\
       
   307 \tline.iBaselineSkip = KB[1]-KB[0];\n\
       
   308 \tline.iNumberOfLinesShown = aNumberOfLinesShown;\n";
       
   309 
       
   310 const string KTextLineExtra = "\
       
   311 \tline.iBaselineSkip = 0;\n\
       
   312 \tline.iNumberOfLinesShown = 1;\n";
       
   313 
       
   314 void CLayoutToInst::AddTextLineToInstance(TLayoutLine& aLine)
       
   315 	{
       
   316 	string apiName = LayoutToCdl::LineApiName(aLine);
       
   317 	if (!HasApi(apiName))
       
   318 		return;
       
   319 	CCdlTkImplementation& imp = FindImp(apiName);
       
   320 	SetFuncLine(imp, aLine, KTypeTextLineLayout, KTextOutputOrder, KTextOutputOrderSize, "", KTextLineExtra);
       
   321 	if (aLine["B"].size() > 1)
       
   322 		{
       
   323 		string preExtra = "\tTInt " + KParamNameB + " = 0;\n";
       
   324 		if (aLine["B"].ParamName() != KParamNameB)
       
   325 			preExtra = "";
       
   326 		string apiName = KFuncMultiline + imp.Name();
       
   327 		if (HasApi(apiName))
       
   328 			{
       
   329 			CCdlTkImplementation& multiLineImp = FindImp(KFuncMultiline + imp.Name());
       
   330 			SetFuncLine(multiLineImp, aLine, KTypeMultiLineTextLayout, KTextOutputOrder, KTextOutputOrderSize, preExtra, KMultiLineTextLineExtra);
       
   331 			}
       
   332 		}
       
   333 	}
       
   334 
       
   335 bool CLayoutToInst::HasApi(const string& aName)
       
   336 	{
       
   337 	return iInterface.ApiList().Find(aName) != 0;
       
   338 	}
       
   339 
       
   340 CCdlTkImplementation& CLayoutToInst::FindImp(const string& aName)
       
   341 	{
       
   342 	CCdlTkImplementation* impl = iInstance->Impl().Find(aName);
       
   343 	if (!impl)
       
   344 		throw NotFoundErr(aName + " in interface " + iInterface.FileName());
       
   345 	return *impl;
       
   346 	}
       
   347 
       
   348 
       
   349 // subtable function uses the main table of pointers, with a mask to ensure that only correct lines are accessed
       
   350 // which are indexed by aLineIndex
       
   351 
       
   352 const string KSubTableImpl = "\
       
   353 #TYPE #NAME#PARAMLIST\n\
       
   354 \t{\n\
       
   355 \tstatic #PTRTYPE const * const KSubTableImpl = (#PTRTYPE const * const)&KCdlImpl.#FIRST_MEMBER;\n\
       
   356 \tASSERT(0<=" + KParamLineIndex + " && " + KParamLineIndex + "<32 && ((1<<" + KParamLineIndex + ") & #VALID_INDEX));\n\
       
   357 \t#PTRTYPE KImpl = KSubTableImpl[" + KParamLineIndex + "];\n\
       
   358 \treturn #EVAL;\n\
       
   359 \t}";
       
   360 
       
   361 const string KSubTableFuncEval = "(*KImpl)(#PARAMNAMES)";
       
   362 const string KSubTableDataEval = "*KImpl";
       
   363 
       
   364 void CLayoutToInst::AddSubTableToInstance(const string& aType, TLayoutTable& aTable, TLayoutTable::TLayoutSubTable& aSubTable, int aTableNum)
       
   365 	{
       
   366 	string apiName = LayoutToCdl::TableApiName(aTable, aSubTable, aTableNum);
       
   367 	if (!HasApi(apiName))
       
   368 		return;
       
   369 
       
   370 	CCdlTkImplementation& imp = FindImp(apiName);
       
   371 	const CCdlTkFunctionApi& api = imp.Api().AsFunc();
       
   372 	const CCdlTkApiParams& params = api.Params();
       
   373 
       
   374 	TLayoutLine& line = *aTable[aSubTable[0]];
       
   375 	CCdlTkImplementation& lineImp = FindImp(LayoutToCdl::LineApiName(line));
       
   376 	const CCdlTkApi& lineApi = lineImp.Api();
       
   377 
       
   378 	string ptrType;
       
   379 	if (lineApi.IsFunc())
       
   380 		ptrType = iInterface.NamespaceName() + "::" + lineApi.PointerType();
       
   381 	else
       
   382 		ptrType = lineApi.PointerType();
       
   383 	
       
   384 	int valid = 0;
       
   385 	for (int ii=0; ii<aTable.size(); ii++)
       
   386 		{
       
   387 		if (find(aSubTable.begin(), aSubTable.end(), ii) != aSubTable.end())
       
   388 			{
       
   389 			valid |= 1<<ii;
       
   390 			}
       
   391 		}
       
   392 
       
   393 	string firstMember = LayoutToCdl::LineApiName(*aTable[0]);
       
   394 
       
   395 	CdlTkUtil::CReplaceSet implSet;
       
   396 	implSet.Add("#TYPE", aType);
       
   397 	implSet.Add("#NAME", imp.Name());
       
   398 	implSet.Add("#PARAMLIST", api.ParamsTypeAndNameList());
       
   399 	implSet.Add("#PTRTYPE", ptrType);
       
   400 	implSet.Add("#FIRST_MEMBER", firstMember);
       
   401 	implSet.Add("#VALID_INDEX", CdlTkUtil::IntToHexString(valid));
       
   402 	implSet.Add("#EVAL", lineApi.IsFunc() ?
       
   403 			CdlTkUtil::Replace("#PARAMNAMES", lineApi.AsFunc().ParamNameList(), KSubTableFuncEval) :
       
   404 			KSubTableDataEval);
       
   405 	string impl = CdlTkUtil::MultiReplace(implSet, KSubTableImpl);
       
   406 
       
   407 	imp.SetTemplatePointerReference();
       
   408 	imp.SetDefinition(impl);
       
   409 	}
       
   410 
       
   411 const string KTableLimitsImpl =
       
   412 KTypeLayoutTableLimits + " #NAME()\n\
       
   413 \t{\n\
       
   414 \tconst " + KTypeLayoutTableLimits + " limits = {#FIRST, #LAST};\n\
       
   415 \treturn limits;\n\
       
   416 \t}";
       
   417 
       
   418 void CLayoutToInst::AddTableLimitsToInstance(TLayoutTable& aTable, TLayoutTable::TLayoutSubTable& aSubTable, int aTableNum)
       
   419 	{
       
   420 	string apiName = LayoutToCdl::TableApiName(aTable, aSubTable, aTableNum)+KFuncLimitsSuffix;
       
   421 	if (!HasApi(apiName))
       
   422 		return;
       
   423 
       
   424 	CCdlTkImplementation& imp = FindImp(apiName);
       
   425 
       
   426 	int first = *aSubTable.begin();
       
   427 	int last = *aSubTable.rbegin();
       
   428 
       
   429 	CdlTkUtil::CReplaceSet implSet;
       
   430 	implSet.Add("#NAME", imp.Name());
       
   431 	implSet.Add("#FIRST", CdlTkUtil::IntToString(first));
       
   432 	implSet.Add("#LAST", CdlTkUtil::IntToString(last));
       
   433 	string impl = CdlTkUtil::MultiReplace(implSet, KTableLimitsImpl);
       
   434 
       
   435 	imp.SetTemplatePointerReference();
       
   436 	imp.SetDefinition(impl);
       
   437 	}
       
   438 
       
   439 
       
   440 // data implementation is a simple const static data declaration
       
   441 
       
   442 const string KDataImpl = "const #TYPEImp #NAME = {#DATA};";
       
   443 const string KDataPtr = "(#TYPE*)&#NAME";
       
   444 
       
   445 void CLayoutToInst::SetDataLine(CCdlTkImplementation& aImp, TLayoutLine& aLine, const string& aType, const string aOutputOrder[], int aOutputOrderSize)
       
   446 	{
       
   447 	string data;
       
   448 	for (int ii=0; ii<aOutputOrderSize; ii++)
       
   449 		{
       
   450 		if (ii != 0)
       
   451 			data += ",";
       
   452 		string value = aLine[aOutputOrder[ii]][0];
       
   453 		CdlTkUtil::AppendString(data, TValues::CppValue(value));
       
   454 		}
       
   455 
       
   456 	CdlTkUtil::CReplaceSet implSet;
       
   457 	implSet.Add("#TYPE", aType);
       
   458 	implSet.Add("#NAME", aImp.Name());
       
   459 	implSet.Add("#DATA", data);
       
   460 	string impl = CdlTkUtil::MultiReplace(implSet, KDataImpl);
       
   461 
       
   462 	CdlTkUtil::CReplaceSet ptrSet;
       
   463 	ptrSet.Add("#TYPE", aType);
       
   464 	ptrSet.Add("#NAME", aImp.Name());
       
   465 	string ptr = CdlTkUtil::MultiReplace(ptrSet, KDataPtr);
       
   466 
       
   467 	aImp.SetPointerReference(ptr);
       
   468 	aImp.SetDefinition(impl);
       
   469 	}
       
   470 
       
   471 
       
   472 // function implementation starts with asserts for parameter ranges and
       
   473 // tables of values for the parameterised cells.
       
   474 // The actual structure is initialised for the fixed values and indexed lookups
       
   475 // on the tables
       
   476 
       
   477 const string KFunctionImpl = "\
       
   478 #TYPE #NAME#PARAMTYPEANDNAMELIST\n\
       
   479 \t{\n\
       
   480 #PRE_EXTRA\
       
   481 #ASSERTS\
       
   482 #TABLES\
       
   483 \t#TYPEImp line = {#INIT};\n\
       
   484 #LOOKUPS\
       
   485 #POST_EXTRA\
       
   486 #RECT_ADJUST\
       
   487 \treturn line;\n\
       
   488 \t}";
       
   489 
       
   490 const string KFunctionAssert = "\tASSERT(0<=#PARAMNAME && #PARAMNAME<#PARAMLIMIT);\n";
       
   491 const string KFunctionTable = "\tconst static TInt16 K#TABLENAME[#PARAMLIMIT] = {#VALUES};\n";
       
   492 const string KFunctionLookup = "\tline.i#TABLENAME = K#TABLENAME[#PARAMNAME];\n";
       
   493 const string KFunctionRect = "\tline.SetAllParentOffsets(" + KParamParentRect + ");\n";
       
   494 
       
   495 void CLayoutToInst::SetFuncLine(CCdlTkImplementation& aImp, TLayoutLine& aLine, const string& aType, const string aOutputOrder[], int aOutputOrderSize, const string& aPreExtra, const string& aPostExtra)
       
   496 	{
       
   497 	const CCdlTkFunctionApi& api = aImp.Api().AsFunc();
       
   498 	const CCdlTkApiParams& params = api.Params();
       
   499 
       
   500 	string asserts;
       
   501 	string tables;
       
   502 	string init;
       
   503 	string lookups;
       
   504 	for (int ii=0; ii<aOutputOrderSize; ii++)
       
   505 		{
       
   506 		TValues& values = aLine[aOutputOrder[ii]];
       
   507 		const string& paramName = values.ParamName();
       
   508 		const string& paramLimit = CdlTkUtil::IntToString(values.size());
       
   509 		const string& tableName = aOutputOrder[ii];
       
   510 
       
   511 		if (ii != 0)
       
   512 			init += ",";
       
   513 		if (values.size() > 1)
       
   514 			{
       
   515 			string v;
       
   516 			for (TValues::iterator pVal = values.begin(); pVal != values.end(); ++pVal)
       
   517 				{
       
   518 				if (pVal != values.begin())
       
   519 					v += ",";
       
   520 				v += TValues::CppValue(*pVal);
       
   521 				}
       
   522 
       
   523 			CdlTkUtil::CReplaceSet replaceSet;
       
   524 			replaceSet.Add("#PARAMNAME", paramName);
       
   525 			replaceSet.Add("#PARAMLIMIT", paramLimit); 
       
   526 			replaceSet.Add("#TABLENAME", tableName); 
       
   527 			replaceSet.Add("#VALUES", v); 
       
   528 
       
   529 			CdlTkUtil::AppendString(asserts, CdlTkUtil::MultiReplace(replaceSet, KFunctionAssert));
       
   530 			CdlTkUtil::AppendString(tables, CdlTkUtil::MultiReplace(replaceSet, KFunctionTable));
       
   531 			CdlTkUtil::AppendString(lookups, CdlTkUtil::MultiReplace(replaceSet, KFunctionLookup));
       
   532 			CdlTkUtil::AppendString(init, "0");
       
   533 			}
       
   534 		else
       
   535 			{
       
   536 			CdlTkUtil::AppendString(init, TValues::CppValue(values[0]));
       
   537 			}
       
   538 		}
       
   539 
       
   540 	string paramTypeAndNameList(api.ParamsTypeAndNameList());
       
   541 	if (aLine.iIsMirroredHorizontally)
       
   542 		MirrorParamNames(paramTypeAndNameList);
       
   543 
       
   544 	CdlTkUtil::CReplaceSet implSet;
       
   545 	implSet.Add("#TYPE", aType);
       
   546 	implSet.Add("#NAME", api.Name());
       
   547 	implSet.Add("#PARAMTYPEANDNAMELIST", paramTypeAndNameList);
       
   548 	implSet.Add("#PRE_EXTRA", aPreExtra);
       
   549 	implSet.Add("#ASSERTS", asserts);
       
   550 	implSet.Add("#TABLES", tables);
       
   551 	implSet.Add("#INIT", init);
       
   552 	implSet.Add("#LOOKUPS", lookups);
       
   553 	implSet.Add("#POST_EXTRA", aPostExtra);
       
   554 	implSet.Add("#RECT_ADJUST", aLine.iNeedsP ? KFunctionRect : "");
       
   555 	string impl = CdlTkUtil::MultiReplace(implSet, KFunctionImpl);
       
   556 
       
   557 	aImp.SetTemplatePointerReference();
       
   558 	aImp.SetDefinition(impl);
       
   559 	}
       
   560 
       
   561 void CLayoutToInst::MirrorParamNames(std::string& aNames)
       
   562 	{
       
   563 	aNames = CdlTkUtil::Replace(KParamNameL, "__tmp__", aNames);
       
   564 	aNames = CdlTkUtil::Replace(KParamNameR, KParamNameL, aNames);
       
   565 	aNames = CdlTkUtil::Replace("__tmp__", KParamNameR, aNames);
       
   566 	}
       
   567 
       
   568 void CLayoutToInst::AddFwdRefToInstance(const string& aName, bool aCast)
       
   569 	{
       
   570 	string ns(CdlTkUtil::ToCpp(iBase->iInstance->Name()));
       
   571 	if (!HasApi(aName))
       
   572 		return;
       
   573 
       
   574 	CCdlTkImplementation& imp = FindImp(aName);
       
   575 	string ptr;
       
   576 	if (aCast)
       
   577 		ptr = string("(") + imp.Api().ReturnType() + "*)";
       
   578 	ptr += string("&") + ns + "::" + aName;
       
   579 	imp.SetPointerReference(ptr);
       
   580 	}
       
   581 
       
   582 
       
   583