diff -r 000000000000 -r f58d6ec98e88 aknlayoutcompiler/src/LayCdl2Inst.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/aknlayoutcompiler/src/LayCdl2Inst.cpp Thu Dec 17 09:14:18 2009 +0200 @@ -0,0 +1,583 @@ +/* +* Copyright (c) 2002-2004 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + + +// disable "identifier was truncated to '255' characters in the browser information" warning +#pragma warning (disable:4786) + +#include "LayCdl2Inst.h" +#include "LayoutCompilerErr.h" +#include "LayoutParse.h" +#include "CppWriter.h" +#include "Lay2Cdl.h" +#include +#include +#include +#include "CodeGenConsts.h" +using namespace std; +using namespace CdlCompilerToolkit; + +typedef LayoutProcessArgsErr LayoutAndCdlToCdlInstanceArgsErr; + + +class LayoutAndCdlToCdlInstanceChecker : public MCdlTkApiCheckObserver + { +private: + void StartCheck(); + void CheckComplete(); + void ApiInBoth(const CCdlTkApi& aApi); + void ApiNotInLeft(const CCdlTkApi& aApi); + void ApiNotInRight(const CCdlTkApi& aApi); + +private: + int iNotInLeft; + int iNotInRight; + }; + + +void LayoutAndCdlToCdlInstanceChecker::StartCheck() + { + iNotInLeft = 0; + iNotInRight = 0; + } + +void LayoutAndCdlToCdlInstanceChecker::CheckComplete() + { + if (iNotInLeft) + cout << "Layout is partial implementation of interface" << endl; + if (iNotInRight) + throw CdlTkAssert("Layout interface check failed"); + } + +void LayoutAndCdlToCdlInstanceChecker::ApiInBoth(const CCdlTkApi& /*aApi*/) + { + } + +void LayoutAndCdlToCdlInstanceChecker::ApiNotInLeft(const CCdlTkApi& /*aApi*/) + { + iNotInLeft++; + } + +void LayoutAndCdlToCdlInstanceChecker::ApiNotInRight(const CCdlTkApi& aApi) + { + iNotInRight++; + cerr << aApi.Name() << " not in interface" << endl; + } + + +int LayoutAndCdlToCdlInstance::Process(const vector& args) + { + if (args.size() < 5 || args.size()%2 == 0) + throw LayoutAndCdlToCdlInstanceArgsErr(); + + string cdlName = args[2]; + CCdlTkCdlFileParser parser(cdlName); + auto_ptr iface(parser.LoadAndParse(true)); + + LayoutAndCdlToCdlInstance process(*iface); + + TLayout* base = NULL; + for (int arg = 3; arg < args.size(); arg += 2) + { + string layoutName = args[arg]; + string instName = args[arg+1]; + auto_ptr layoutParse = TLayParseLayout::Parse(layoutName); + auto_ptr layout(layoutParse.get()); + layoutParse.release(); + if (base) + { + auto_ptr newLayout(new TLayout(*base)); + newLayout->Merge(TLayout::KMergeModeVariant, *layout); + layout = newLayout; + } + else + { + base = layout.get(); + } + process.AddLayout(layout, instName); + } + + process.WriteInstances(); + + return 0; + } + +void LayoutAndCdlToCdlInstance::ShowHelp(ostream& stream) + { + stream << "LayCdl2Inst ( )+ " << endl; + stream << " Creates CDL instances containing the layout data." << endl; + stream << " All layout instances must conform to the CDL interface." << endl; + stream << " If more than one layout is supplied, subsequent ones are treated as" << endl; + stream << " variants of the first." << endl; + } + +void LayoutAndCdlToCdlInstance::CheckLayoutAgainstInterface(const TLayout& aLayout, const CCdlTkInterface& aIface) + { + auto_ptr layIface = LayoutToCdl::LayoutToInterface(aLayout); + LayoutAndCdlToCdlInstanceChecker checker; + CCdlTkApiChecker check(*layIface, aIface, checker); + check.Process(); + } + +LayoutAndCdlToCdlInstance::LayoutAndCdlToCdlInstance(CCdlTkInterface& aInterface) +: iInterface(aInterface) + { + } + +LayoutAndCdlToCdlInstance::~LayoutAndCdlToCdlInstance() + { + for (CLayouts::iterator pLayout = iLayouts.begin(); pLayout != iLayouts.end(); ++pLayout) + delete *pLayout; + } + +void LayoutAndCdlToCdlInstance::AddLayout(auto_ptr& aLayout, const string& aInstName) + { + CLayoutToInst* base = NULL; + if (iLayouts.size()) + base = iLayouts[0]; + auto_ptr p(new CLayoutToInst(base, iInterface, aLayout, aInstName)); + iLayouts.push_back(p.get()); + p.release(); + } + +void LayoutAndCdlToCdlInstance::WriteInstances() + { + CLayouts::iterator pLayout = iLayouts.begin(); + CLayouts::iterator end = iLayouts.end(); + + if (pLayout!=end) + (*pLayout)->Process(); + + for (; pLayout != end; ++pLayout) + { + CCdlTkWriteInstance writer((*pLayout)->Instance()); + writer.Process(); + } + } + + +CLayoutToInst::CLayoutToInst(CLayoutToInst* aBase, CCdlTkInterface& aInterface, auto_ptr& aLayout, const string& aInstName) +: iBase(aBase), iInterface(aInterface), iLayout(*aLayout), iInstName(aInstName) + { + iLayoutPtr = aLayout.get(); + aLayout.release(); + + iInstance = new CCdlTkInstance(iInterface); + iInstance->SetName(aInstName); + + string extraCpp("#include \n"); + extraCpp += string("#include \"") + CdlTkUtil::ToLower(aBase ? aBase->FwdDeclName() : FwdDeclName()) + "\"\n"; + iInstance->SetExtraCpp(extraCpp); + + for (TLayout::iterator pTab = iLayout.begin(); pTab != iLayout.end(); ++pTab) + { + AddTableToInstance(**pTab); + } + } + +CLayoutToInst::~CLayoutToInst() + { + delete iInstance; + delete iLayoutPtr; + } + +string CLayoutToInst::FwdDeclName() + { + if (iBase) + return iBase->FwdDeclName(); + else + return iInstName + ".FwdDecl.h"; + } + +void CLayoutToInst::Process() + { + string fileName(FwdDeclName()); + string interfaceNsName = iInterface.NamespaceName(); + + ofstream stream; + CCdlTkFileCleanup tempFile; + CdlTkUtil::OpenTempOutput(stream, tempFile); + + WriteHeaderGuardStart(fileName, stream); + stream << "namespace " << CdlTkUtil::ToCpp(iInstance->Name()) << endl; + stream << "{" << endl; + + CCdlTkApiList& apiList = iInterface.ApiList(); + for (CCdlTkApiList::iterator pApi = apiList.begin(); pApi != apiList.end(); ++pApi) + { + if ((*pApi)->IsFunc()) + { + stream << "extern " << interfaceNsName << "::" << (*pApi)->AsFunc().ApiNameAsTypeName() << " " << (*pApi)->Name() << ";" << endl; + } + else + { + string typeExt = "Imp"; + if ((*pApi)->ReturnType() == KTypeLayoutTableLimits) + typeExt = ""; + stream << "extern " << (*pApi)->ReturnType() << typeExt << " const " << (*pApi)->Name() << ";" << endl; + } + } + + stream << "}" << endl << endl; + WriteHeaderGuardEnd(fileName, stream); + + stream.close(); + CdlTkUtil::ExportFile(tempFile, CdlTkUtil::OutputPath() + fileName); + } + +CCdlTkInstance& CLayoutToInst::Instance() + { + return *iInstance; + } + +void CLayoutToInst::AddTableToInstance(TLayoutTable& aTable) + { + for (TLayoutTable::iterator pLine = aTable.begin(); pLine != aTable.end(); ++pLine) + { + TLayoutLine& line = **pLine; + if (line.iIsMergedIdentical) + { + string apiName = LayoutToCdl::LineApiName(line); + AddFwdRefToInstance(apiName, false); + + string multilineApiName = KFuncMultiline + apiName; + if (aTable.iType == TLayoutTable::ETextTable && + line["B"].size() > 1 && + HasApi(multilineApiName)) + { + AddFwdRefToInstance(multilineApiName, false); + } + } + else + { + if (aTable.iType == TLayoutTable::EWindowTable) + AddWindowLineToInstance(line); + else + AddTextLineToInstance(line); + } + } + + int tableNum = 0; + for (TLayoutTable::TLayoutSubTables::const_iterator pSub = aTable.iSubTables.begin(); pSub != aTable.iSubTables.end(); ++pSub) + { + TLayoutTable::TLayoutSubTable& sub = **pSub; + if (sub.iIsMergedIdentical) + { + AddFwdRefToInstance(LayoutToCdl::TableApiName(aTable, sub, tableNum)+KFuncLimitsSuffix, false); + AddFwdRefToInstance(LayoutToCdl::TableApiName(aTable, sub, tableNum), false); + } + else + { + AddTableLimitsToInstance(aTable, sub, tableNum); + string tableType = KTypeTextLineLayout; + if (aTable.iType == TLayoutTable::EWindowTable) + tableType = KTypeWindowLineLayout; + AddSubTableToInstance(tableType, aTable, sub, tableNum); + } + tableNum++; + } + } + +void CLayoutToInst::AddWindowLineToInstance(TLayoutLine& aLine) + { + string apiName = LayoutToCdl::LineApiName(aLine); + if (!HasApi(apiName)) + return; + CCdlTkImplementation& imp = FindImp(apiName); + SetFuncLine(imp, aLine, KTypeWindowLineLayout, KWindowOutputOrder, KWindowOutputOrderSize, "", ""); + } + +const string KMultiLineTextLineExtra = "\ +\tline.iB = KB[0];\n\ +\tline.iBaselineSkip = KB[1]-KB[0];\n\ +\tline.iNumberOfLinesShown = aNumberOfLinesShown;\n"; + +const string KTextLineExtra = "\ +\tline.iBaselineSkip = 0;\n\ +\tline.iNumberOfLinesShown = 1;\n"; + +void CLayoutToInst::AddTextLineToInstance(TLayoutLine& aLine) + { + string apiName = LayoutToCdl::LineApiName(aLine); + if (!HasApi(apiName)) + return; + CCdlTkImplementation& imp = FindImp(apiName); + SetFuncLine(imp, aLine, KTypeTextLineLayout, KTextOutputOrder, KTextOutputOrderSize, "", KTextLineExtra); + if (aLine["B"].size() > 1) + { + string preExtra = "\tTInt " + KParamNameB + " = 0;\n"; + if (aLine["B"].ParamName() != KParamNameB) + preExtra = ""; + string apiName = KFuncMultiline + imp.Name(); + if (HasApi(apiName)) + { + CCdlTkImplementation& multiLineImp = FindImp(KFuncMultiline + imp.Name()); + SetFuncLine(multiLineImp, aLine, KTypeMultiLineTextLayout, KTextOutputOrder, KTextOutputOrderSize, preExtra, KMultiLineTextLineExtra); + } + } + } + +bool CLayoutToInst::HasApi(const string& aName) + { + return iInterface.ApiList().Find(aName) != 0; + } + +CCdlTkImplementation& CLayoutToInst::FindImp(const string& aName) + { + CCdlTkImplementation* impl = iInstance->Impl().Find(aName); + if (!impl) + throw NotFoundErr(aName + " in interface " + iInterface.FileName()); + return *impl; + } + + +// subtable function uses the main table of pointers, with a mask to ensure that only correct lines are accessed +// which are indexed by aLineIndex + +const string KSubTableImpl = "\ +#TYPE #NAME#PARAMLIST\n\ +\t{\n\ +\tstatic #PTRTYPE const * const KSubTableImpl = (#PTRTYPE const * const)&KCdlImpl.#FIRST_MEMBER;\n\ +\tASSERT(0<=" + KParamLineIndex + " && " + KParamLineIndex + "<32 && ((1<<" + KParamLineIndex + ") & #VALID_INDEX));\n\ +\t#PTRTYPE KImpl = KSubTableImpl[" + KParamLineIndex + "];\n\ +\treturn #EVAL;\n\ +\t}"; + +const string KSubTableFuncEval = "(*KImpl)(#PARAMNAMES)"; +const string KSubTableDataEval = "*KImpl"; + +void CLayoutToInst::AddSubTableToInstance(const string& aType, TLayoutTable& aTable, TLayoutTable::TLayoutSubTable& aSubTable, int aTableNum) + { + string apiName = LayoutToCdl::TableApiName(aTable, aSubTable, aTableNum); + if (!HasApi(apiName)) + return; + + CCdlTkImplementation& imp = FindImp(apiName); + const CCdlTkFunctionApi& api = imp.Api().AsFunc(); + const CCdlTkApiParams& params = api.Params(); + + TLayoutLine& line = *aTable[aSubTable[0]]; + CCdlTkImplementation& lineImp = FindImp(LayoutToCdl::LineApiName(line)); + const CCdlTkApi& lineApi = lineImp.Api(); + + string ptrType; + if (lineApi.IsFunc()) + ptrType = iInterface.NamespaceName() + "::" + lineApi.PointerType(); + else + ptrType = lineApi.PointerType(); + + int valid = 0; + for (int ii=0; ii 1) + { + string v; + for (TValues::iterator pVal = values.begin(); pVal != values.end(); ++pVal) + { + if (pVal != values.begin()) + v += ","; + v += TValues::CppValue(*pVal); + } + + CdlTkUtil::CReplaceSet replaceSet; + replaceSet.Add("#PARAMNAME", paramName); + replaceSet.Add("#PARAMLIMIT", paramLimit); + replaceSet.Add("#TABLENAME", tableName); + replaceSet.Add("#VALUES", v); + + CdlTkUtil::AppendString(asserts, CdlTkUtil::MultiReplace(replaceSet, KFunctionAssert)); + CdlTkUtil::AppendString(tables, CdlTkUtil::MultiReplace(replaceSet, KFunctionTable)); + CdlTkUtil::AppendString(lookups, CdlTkUtil::MultiReplace(replaceSet, KFunctionLookup)); + CdlTkUtil::AppendString(init, "0"); + } + else + { + CdlTkUtil::AppendString(init, TValues::CppValue(values[0])); + } + } + + string paramTypeAndNameList(api.ParamsTypeAndNameList()); + if (aLine.iIsMirroredHorizontally) + MirrorParamNames(paramTypeAndNameList); + + CdlTkUtil::CReplaceSet implSet; + implSet.Add("#TYPE", aType); + implSet.Add("#NAME", api.Name()); + implSet.Add("#PARAMTYPEANDNAMELIST", paramTypeAndNameList); + implSet.Add("#PRE_EXTRA", aPreExtra); + implSet.Add("#ASSERTS", asserts); + implSet.Add("#TABLES", tables); + implSet.Add("#INIT", init); + implSet.Add("#LOOKUPS", lookups); + implSet.Add("#POST_EXTRA", aPostExtra); + implSet.Add("#RECT_ADJUST", aLine.iNeedsP ? KFunctionRect : ""); + string impl = CdlTkUtil::MultiReplace(implSet, KFunctionImpl); + + aImp.SetTemplatePointerReference(); + aImp.SetDefinition(impl); + } + +void CLayoutToInst::MirrorParamNames(std::string& aNames) + { + aNames = CdlTkUtil::Replace(KParamNameL, "__tmp__", aNames); + aNames = CdlTkUtil::Replace(KParamNameR, KParamNameL, aNames); + aNames = CdlTkUtil::Replace("__tmp__", KParamNameR, aNames); + } + +void CLayoutToInst::AddFwdRefToInstance(const string& aName, bool aCast) + { + string ns(CdlTkUtil::ToCpp(iBase->iInstance->Name())); + if (!HasApi(aName)) + return; + + CCdlTkImplementation& imp = FindImp(aName); + string ptr; + if (aCast) + ptr = string("(") + imp.Api().ReturnType() + "*)"; + ptr += string("&") + ns + "::" + aName; + imp.SetPointerReference(ptr); + } + + +