Merge branch 'lua_versions' into main/rendor-staging
[ryzomcore.git] / ryzom / tools / pd_parser / parser.cpp
blob0d4629726c146e544386135add41b2bb432be8cc
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2015-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "parser.h"
22 #include "cpp_output.h"
23 #include "templatizer.h"
25 #include "parser_rules.h"
27 #include <nel/misc/path.h>
28 #include <nel/misc/sha1.h>
30 using namespace std;
31 using namespace NLMISC;
32 //using namespace RY_PDS;
35 bool GenerateCpp = true;
36 bool GenerateXmlDescription = true;
37 bool VerboseMode = false;
38 bool GenerateDebugMessages = false;
39 bool GenerateHAuto = false;
40 bool GenerateOnlyLogs = false;
43 CTokenizer Tokenizer;
44 CTemplatizer Templatizer;
45 CHashKey HashKey;
47 string CurrentEnum;
48 CEnumNode *CurrentEnumNode = NULL;
50 string DbDescriptionVersion("0.0");
52 string formatDescription(const string &str)
54 string result;
56 uint pos = 0;
58 while (pos < str.size() && (str[pos] == ' ' || str[pos] == '\t' || str[pos] == '\r' || str[pos] == '\n'))
59 ++pos;
61 bool first = true;
63 while (pos < str.size())
65 if (!first)
66 result += "\n";
67 first = false;
69 result += "* ";
71 while (pos < str.size() && str[pos] != '\n')
72 result += str[pos++];
74 while (pos < str.size() && (str[pos] == ' ' || str[pos] == '\t' || str[pos] == '\r' || str[pos] == '\n'))
75 ++pos;
78 return result;
81 string strReplace(string str, const string &search, const string &replace)
83 std::string::size_type pos = 0;
84 while ((pos = str.find(search)) != string::npos)
85 str.replace(pos, search.size(), replace);
86 return str;
89 string xmlSpecialChars(string str)
91 str = strReplace(str, "&", "&amp;");
92 str = strReplace(str, "<", "&lt;");
93 str = strReplace(str, ">", "&gt;");
94 str = strReplace(str, "\"", "&quot;");
95 str = strReplace(str, "'", "&apos;");
97 return str;
100 string getFullStdPathNoExt(const string &path)
102 string dir = NLMISC::toLowerAscii(NLMISC::CFile::getPath(path));
103 string file = NLMISC::toLowerAscii(NLMISC::CFile::getFilenameWithoutExtension(path));
105 return dir.empty() ? file : NLMISC::CPath::standardizePath(dir)+file;
108 string getFullStdPath(const string &path)
110 string dir = NLMISC::toLowerAscii(NLMISC::CFile::getPath(path));
111 string file = NLMISC::toLowerAscii(NLMISC::CFile::getFilename(path));
113 return dir.empty() ? file : NLMISC::CPath::standardizePath(dir)+file;
116 string appendArg(const std::string& firstArgs, const std::string& nextArg)
118 if (firstArgs.empty())
119 return nextArg;
120 return firstArgs + ", " + nextArg;
124 * Start parsing
126 CParseNode *parse(const string &file)
128 HashKey = getSHA1(file);
130 Tokenizer.readFile(file);
132 if (Tokenizer.tokenize())
133 return parseMain(Tokenizer);
134 return NULL;
140 * Execute nodes
143 // DB Node
144 bool CDbNode::prolog()
146 addTypeNode("CSheetId", "NLMISC::CSheetId", "NLMISC::CSheetId::Unknown");
147 addTypeNode("CEntityId", "NLMISC::CEntityId", "NLMISC::CEntityId::Unknown");
148 addTypeNode("double", "double", "0.0");
149 addTypeNode("float", "float", "0.0f");
150 addTypeNode("sint64", "sint64", "(sint64)0");
151 addTypeNode("uint64", "uint64", "(uint64)0");
152 addTypeNode("sint32", "sint32", "0");
153 addTypeNode("uint32", "uint32", "0");
154 addTypeNode("sint16", "sint16", "0");
155 addTypeNode("uint16", "uint16", "0");
156 addTypeNode("sint8", "sint8", "0");
157 addTypeNode("uint8", "uint8", "0");
158 addTypeNode("ucchar", "ucchar", "0");
159 addTypeNode("char", "char", "0");
160 addTypeNode("bool", "bool", "false");
162 return true;
167 bool inlineAccessors = false;
168 string getFunctionPrefix = "get";
169 string setFunctionPrefix = "set";
170 string newFunction = "addTo";
171 string deleteFunction = "deleteFrom";
173 string indexVariable = "__i";
174 string valueVariable = "__v";
175 string keyVariable = "__k";
176 string objectVariable = "__o";
178 bool inlineUserInitDefaultCode = false;
179 string userInitFunction = "init";
180 string userReleaseFunction = "release";
182 bool inlineStaticPublic = false;
183 string staticCreateFunction = "create";
184 string staticRemoveFunction = "remove";
185 string staticSetUserFactoryFunction = "setFactory";
186 string staticLoadFunction = "load";
187 string staticUnloadFunction = "unload";
188 string staticSetLoadCbFunction = "setLoadCallback";
189 string staticGetFunction = "get";
190 string staticCastFunction = "cast";
191 string staticConstCastFunction = "cast";
192 string staticBeginFunction = "begin";
193 string staticEndFunction = "end";
195 bool inlineInternal = false;
196 string initFunction = "pds__init";
197 string destroyFunction = "pds__destroy";
198 string registerFunction = "pds__register";
199 string registerAttributesFunction = "pds__registerAttributes";
200 string unregisterFunction = "pds__unregister";
201 string unregisterAttributesFunction = "pds__unregisterAttributes";
202 string fetchFunction = "pds__fetch";
203 string setParentFunction = "pds__setParent";
204 string setUnnotifiedParentFunction = "pds__setParentUnnotified";
205 string getTableFunction = "pds__getTable";
206 string unlinkFunction = "pds__unlink";
207 string notifyInitFunction = "pds__notifyInit";
208 string notifyReleaseFunction = "pds__notifyRelease";
210 string clearFunction = "clear";
211 string storeFunction = "store";
212 string applyFunction = "apply";
213 string declareTokensFunction = "pds__declareTokens";
216 bool inlineStaticInternal = false;
217 string staticInitFactoryFunction = "pds_static__setFactory";
218 string staticFactoryFunction = "pds_static__factory";
219 string staticFetchFunction = "pds_static__fetch";
220 string staticInitFunction = "pds_static__init";
221 string staticNotifyLoadFailure = "pds_static__notifyFailure";
222 string staticLoadCbAttribute = "__pds__LoadCallback";
224 bool inlineLog = false;
225 string logStartFunction = "pds__startLog";
226 string logStopFunction = "pds__stopLog";
228 string PDSNamespace = "RY_PDS";
229 string CPDSLibName = PDSNamespace+"::CPDSLib";
230 string objectIndexName = PDSNamespace+"::CObjectIndex";
231 string nullIndexName = PDSNamespace+"::CObjectIndex::null()";
232 string TTableIndexName = PDSNamespace+"::TTableIndex";
233 string TRowIndexName = PDSNamespace+"::TRowIndex";
234 string TColumnIndexName = PDSNamespace+"::TColumnIndex";
235 string INVALID_TABLE_INDEXName = PDSNamespace+"::INVALID_TABLE_INDEX";
236 string INVALID_ROW_INDEXName = PDSNamespace+"::INVALID_ROW_INDEX";
237 string indexAllocatorName = PDSNamespace+"::CIndexAllocator";
238 string pdBaseDataName = PDSNamespace+"::IPDBaseData";
239 //string pdBaseInheritDataName = PDSNamespace+"::IPDBaseInheritData";
240 string CPDataName = PDSNamespace+"::CPData";
241 string TPDFactoryName = PDSNamespace+"::TPDFactory";
242 string TPDFetchName = PDSNamespace+"::TPDFetch";
243 string TPDFetchFailureName = PDSNamespace+"::TPDFetchFailure";
245 bool inlineLogFunctions = false;
247 string pdslibFunc(const std::string& func)
249 //return CPDSLibName+"::"+func;
250 return "PDSLib."+func;
253 bool CDbNode::epilog()
255 uint i;
257 Env = Templatizer.RootEnv;
258 setEnv("db", Name);
260 string fullfile = getFullStdPathNoExt(MainFile.empty() ? Name : MainFile);
261 string filename = NLMISC::toLowerAscii(NLMISC::CFile::getFilenameWithoutExtension(fullfile));
263 setEnv("filename", filename);
264 setEnv("fullfilename", fullfile);
265 setEnv("headerfilename", strReplace(strupr(filename+".h"), ".", "_"));
267 DbHpp.setFileHeader(filename+".h", "Initialisation of the "+Name+" database, declarations\n"+Description);
268 DbCpp.setFileHeader(filename+".cpp", "Initialisation of the "+Name+" database, implementation\n"+Description);
269 DbHppInline.setFileHeader(filename+"_inline.h", "Initialisation of the "+Name+" database, inline implementation\n"+Description);
271 DbSummary << "\n\n";
272 DbSummary << "Summary of " << Name << " database classes of database\n";
273 DbSummary << "-----------------------------------------------------------------------------\n\n";
274 DbSummary << "This file is automatically generated.\n";
275 DbSummary << "This is a reminder of all classes generated and methods implemented.\n\n\n";
277 DbSummary << "Database " << Name << " is managed through 4 functions located in " << fullfile << ".h:\n\n";
279 DbSummary << Name << "::init():\n";
280 DbSummary << "Initialises database context and connection towards database server (refered as PDS).\n";
281 DbSummary << "All user factories must have been set before call to this function.\n";
282 DbSummary << "Call this function in service init method.\n\n";
284 DbSummary << Name << "::ready():\n";
285 DbSummary << "Tells whether the whole database engine is ready to work.\n";
286 DbSummary << "You must not update any value nor call update() unless ready() is true.\n\n";
288 DbSummary << Name << "::update():\n";
289 DbSummary << "Updates the database engine and sends updates to the PDS.\n";
290 DbSummary << "Call this function each tick, provided ready() returned true.\n\n";
292 DbSummary << Name << "::release():\n";
293 DbSummary << "Releases the database engine. Drops all data, closes the connection to the PDS.\n";
294 DbSummary << "Call this function in service release method.\n\n";
296 DbSummary << "\n\n";
297 DbSummary << "Summary of generated classes for " << Name << "\n\n";
299 DbHpp << "\n#ifndef " << strReplace(strupr(filename+".h"), ".", "_") << "\n";
300 DbHpp << "#define " << strReplace(strupr(filename+".h"), ".", "_") << "\n";
301 DbHpp << "\n";
302 DbHpp << "#include <nel/misc/types_nl.h>\n";
303 DbHpp << "#include <pd_lib/pd_lib.h>\n";
304 DbHpp << "\n";
305 DbHpp << "namespace " << Name << "\n{\n\n";
306 DbHpp.unindent();
308 if (!Pch.empty())
310 DbCpp << "\n#include \"" << Pch << "\"\n\n";
313 DbCpp << "#include \"" << filename << ".h\"\n\n";
314 DbCpp << "namespace " << Name << "\n{\n\n";
315 DbCpp.unindent();
317 DbCpp << "RY_PDS::CPDSLib PDSLib;\n";
319 DbHppInline << "namespace " << Name << "\n{\n\n";
320 DbHppInline.unindent();
323 uint maxClassId = 0;
324 for (i=0; i<ClassNodes.size(); ++i)
326 CClassNode *classnd = ClassNodes[i];
327 ++maxClassId;
330 uint maxTypeId = 0;
331 for (i=0; i<TypeNodes.size(); ++i)
333 CTypeNode *typend = TypeNodes[i];
334 ++maxTypeId;
337 xmlDescription.clear();
338 xmlDescription.push_back("<?xml version='1.0'?>");
339 xmlDescription.push_back("<dbdescription version='"+DbDescriptionVersion+"'>");
340 //xmlDescription.push_back("<db name='"+Name+"' types='"+toString(maxTypeId)+"' classes='"+toString(maxClassId)+"' hashkey='"+HashKey.toString()+"'>");
341 xmlDescription.push_back("<db name='"+Name+"' types='"+toString(maxTypeId)+"' classes='"+toString(maxClassId)+"'>");
343 pass1();
345 pass2();
347 pass3();
349 // Check dependencies order
350 vector<CClassNode*> classesOrder;
351 vector<CFileNode*> filesOrder;
352 buildClassOrder(classesOrder, filesOrder);
354 // generate all file prologs
355 for (i=0; i<FileNodes.size(); ++i)
357 CFileNode *child = FileNodes[i];
358 child->generateProlog();
361 pass4();
364 initDb.init("init");
365 initDb.IsInline = false;
366 initDb.Proto = "uint32 overrideDbId";
367 initDb.Type = "void";
368 initDb.Description = "Initialise the whole database engine.\nCall this function at service init.";
370 readyDb.init("ready");
371 readyDb.IsInline = false;
372 readyDb.Proto.clear();
373 readyDb.Type = "bool";
374 readyDb.Description = "Tells if database engine is ready to work.\nEngine may not be ready because PDS is down, not yet ready\nor message queue to PDS is full.";
376 updateDb.init("update");
377 updateDb.IsInline = false;
378 updateDb.Proto.clear();
379 updateDb.Type = "void";
380 updateDb.Description = "Update the database engine.\nCall this method once per tick, only if engine is ready (see also ready() above).";
382 logChatDb.init("logChat");
383 logChatDb.IsInline = false;
384 logChatDb.Proto = "const ucstring& sentence, const NLMISC::CEntityId& from, const std::vector<NLMISC::CEntityId>& to";
385 logChatDb.Type = "void";
386 logChatDb.Description = "Logs chat sentence with sender and receipiants.";
388 logTellDb.init("logTell");
389 logTellDb.IsInline = false;
390 logTellDb.Proto = "const ucstring& sentence, const NLMISC::CEntityId& from, const NLMISC::CEntityId& to";
391 logTellDb.Type = "void";
392 logTellDb.Description = "Logs tell sentence with sender and single recipient (might be player or group).";
394 releaseDb.init("release");
395 releaseDb.IsInline = false;
396 releaseDb.Proto.clear();
397 releaseDb.Type = "void";
398 releaseDb.Description = "Release the whole database engine.\nCall this function at service release.";
401 generateClassesDeclaration();
404 generateClassesContent(classesOrder);
407 generateLogContent();
409 xmlDescription.push_back("</db>");
410 xmlDescription.push_back("</dbdescription>");;
412 initDb.add("std::string\txmlDescription;");
414 DbXml.setXmlMode();
416 for (i=0; i<xmlDescription.size(); ++i)
418 initDb.add("xmlDescription += \""+xmlDescription[i]+"\\n\";");
419 DbXml << xmlDescription[i] << "\n";
422 DbXml.flush(fullfile+".xml");
424 DbHpp << "/// \\name Public API for " << Name << " database\n";
425 DbHpp << "// @{\n";
426 DbHpp.unindent();
428 initDb.add(pdslibFunc("init")+"(xmlDescription, overrideDbId);");
429 initDb.flush(DbHpp, DbCpp, DbHppInline);
431 readyDb.add("return "+pdslibFunc("PDSReady")+"();");
432 readyDb.flush(DbHpp, DbCpp, DbHppInline);
434 updateDb.add(pdslibFunc("update")+"();");
435 updateDb.flush(DbHpp, DbCpp, DbHppInline);
437 logChatDb.add(pdslibFunc("logChat")+"(sentence, from, to);");
438 logChatDb.flush(DbHpp, DbCpp, DbHppInline);
440 logTellDb.add("std::vector<NLMISC::CEntityId>\tids;");
441 logTellDb.add("ids.push_back(to);");
442 logTellDb.add(pdslibFunc("logChat")+"(sentence, from, ids);");
443 logTellDb.flush(DbHpp, DbCpp, DbHppInline);
445 releaseDb.add(pdslibFunc("release")+"();");
446 releaseDb.flush(DbHpp, DbCpp, DbHppInline);
448 DbHpp << "\n// @}\n\n";
450 DbHpp << "extern RY_PDS::CPDSLib PDSLib;\n";
452 DbHpp.indent();
453 DbHpp << "\n} // End of " << Name <<"\n";
455 generateIncludes(filesOrder);
457 DbHpp << "\n#include \"" << filename << "_inline.h\"\n\n";
458 DbHpp << "\n#endif\n";
459 DbHpp.flush(fullfile+".h");
461 DbCpp.indent();
462 DbCpp << "\n} // End of " << Name <<"\n";
463 DbCpp.flush(fullfile+".cpp");
465 DbHppInline.indent();
466 DbHppInline << "\n} // End of " << Name <<"\n";
467 DbHppInline.flush(fullfile+"_inline.h");
469 DbSummary.flush(fullfile+"_summary.txt");
471 for (i=0; i<FileNodes.size(); ++i)
473 CFileNode *child = FileNodes[i];
474 child->generateEpilog();
477 return true;
482 void CDbNode::pass1()
485 * PASS 1
486 * - all type names and class names are known
487 * -> look for classes in set or backreferences
490 uint i;
492 uint classId = 0;
493 uint typeId = 0;
495 for (i=0; i<ClassNodes.size(); ++i)
497 CClassNode *classnd = ClassNodes[i];
498 classnd->checkClassReferences();
499 classnd->Id = classId++;
501 classnd->getFileNode()->IncludeStandard = true;
502 classnd->getFileNode()->IncludeDbFile = true;
505 for (i=0; i<TypeNodes.size(); ++i)
507 CTypeNode *typend = TypeNodes[i];
509 typend->Id = typeId++;
511 uint tsize = 0;
512 if (typend->StorageType == "bool") tsize = 1;
513 if (typend->StorageType == "char") tsize = 1;
514 if (typend->StorageType == "ucchar") tsize = 2;
515 if (typend->StorageType == "uint8") tsize = 1;
516 if (typend->StorageType == "sint8") tsize = 1;
517 if (typend->StorageType == "uint16") tsize = 2;
518 if (typend->StorageType == "sint16") tsize = 2;
519 if (typend->StorageType == "uint32") tsize = 4;
520 if (typend->StorageType == "sint32") tsize = 4;
521 if (typend->StorageType == "uint64") tsize = 8;
522 if (typend->StorageType == "sint64") tsize = 8;
523 if (typend->StorageType == "float") tsize = 4;
524 if (typend->StorageType == "double") tsize = 8;
525 if (typend->StorageType == "CEntityId") tsize = 8;
526 if (typend->StorageType == "CSheetId") tsize = 4;
528 typend->Size = tsize;
530 string xmlnode = "<typedef name='"+typend->Name+"' id='"+toString(typend->Id)+"' size='"+toString(tsize)+"' storage='"+typend->StorageType+"'";
532 if (typend->isEnum())
534 CEnumNode *enumnd = static_cast<CEnumNode*>(typend);
536 xmlnode += " type='enum'>";
537 xmlDescription.push_back(xmlnode);
538 uint j;
539 for (j=0; j<enumnd->Values.size(); ++j)
540 xmlDescription.push_back("<enumvalue name='"+enumnd->Values[j].first+"' value='"+toString(enumnd->Values[j].second)+"'/>");
541 xmlDescription.push_back("</typedef>");
543 else if (typend->isDimension())
545 CDimensionNode *dimnd = static_cast<CDimensionNode*>(typend);
547 xmlnode += " type='dimension' dimension='"+toString(dimnd->Dimension)+"'/>";
548 xmlDescription.push_back(xmlnode);
550 else
552 xmlnode += " type='type'/>";
553 xmlDescription.push_back(xmlnode);
558 void CDbNode::pass2()
561 * PASS 2
562 * - class hierarchy, backreferences and in set information are known
563 * -> fill up attributes
566 uint i;
568 for (i=0; i<ClassNodes.size(); ++i)
570 CClassNode *child = ClassNodes[i];
572 if (!child->Inherited.empty() && child->MappedFlag && !child->HasParent)
573 child->error("class cannot inherit another class and be mapped. Try to map base class instead.");
575 if (child->MappedFlag && child->getClassKey() == NULL)
576 child->error("class is mapped and has no key defined");
578 child->ForceReference = (child->HasInheritance || child->MappedFlag || child->DerivatedFlag || (child->HasParent && !child->ParentIsHidden));
580 if (child->ForceReference && child->ParentIsHidden)
581 child->error("Parent attribute cannot be hidden because class has inheritance, is mapped or is derivated.");
583 child->getFileNode()->IncludePDSLib = true;
585 if (!child->Inherited.empty())
587 CClassNode *icln = child;
588 CClassNode *lastMapped = (child->MappedFlag ? child : NULL);
589 while (!icln->Inherited.empty())
591 icln = getClassNode(icln->Inherited);
592 if (icln->MappedFlag)
594 if (lastMapped != NULL)
595 lastMapped->error("class cannot be remapped since parent "+icln->Name+" is already mapped");
596 lastMapped = icln;
601 if (icln->MappedFlag)
602 child->MapClass = icln;
604 child->MapClass = lastMapped;
606 else if (child->MappedFlag)
608 child->MapClass = child;
611 child->fillAttributes();
616 void CDbNode::pass3()
619 * PASS 3
620 * - attributes are known
621 * -> fill up backrefs and array/set forwardrefs
624 uint i;
626 for (i=0; i<ClassNodes.size(); ++i)
628 CClassNode *child = ClassNodes[i];
629 child->fillRefs();
632 for (i=0; i<ClassNodes.size(); ++i)
634 CClassNode *child = ClassNodes[i];
635 child->computeFriends();
639 void CDbNode::pass4()
642 * PASS 4
643 * - everything is ok in database descriptor
644 * -> output c++ code
647 uint i;
649 for (i=0; i<FileNodes.size(); ++i)
651 CFileNode* file = FileNodes[i];
652 file->Hpp << "\n\n//\n// Typedefs & Enums\n//\n\n";
655 for (i=0; i<TypeNodes.size(); ++i)
657 CTypeNode *type = TypeNodes[i];
658 if (type->ExternFlag || type->InternFlag)
659 continue;
661 type->generateContent();
668 void CDbNode::generateClassesDeclaration()
670 uint i;
672 DbHpp << "\n//\n";
673 DbHpp << "// Global Forward Declarations\n";
674 DbHpp << "//\n\n";
676 for (i=0; i<ClassNodes.size(); ++i)
678 DbHpp << "class " << ClassNodes[i]->Name << ";\n";
681 DbHpp << "\n";
682 DbHpp << "//\n\n";
685 void CDbNode::generateIncludes(vector<CFileNode*>& filesOrder)
687 uint i;
689 DbHpp << "\n//\n";
690 DbHpp << "// Includes\n";
691 DbHpp << "//\n\n";
693 for (i=0; i<filesOrder.size(); ++i)
695 if (!filesOrder[i]->SeparatedFlag)
697 filesOrder[i]->setEnv("as", getFileNoExtPath(filesOrder[i]->IncludeAs));
698 DbHpp << "#include \"" << getFileNoExtPath(filesOrder[i]->IncludeAs) << ".h\"\n";
702 DbHpp << "\n";
704 for (i=0; i<filesOrder.size(); ++i)
706 if (filesOrder[i]->IncludeDbFile && !filesOrder[i]->SeparatedFlag)
708 filesOrder[i]->define("incinline");
709 DbHpp << "#include \"" << getFileNoExtPath(filesOrder[i]->IncludeAs) << "_inline.h\"\n";
713 DbHpp << "\n";
714 DbHpp << "//\n\n";
717 void CDbNode::generateClassesContent(vector<CClassNode*>& classesOrder)
719 uint i;
722 // output classes content
724 for (i=0; i<classesOrder.size(); ++i)
726 CClassNode *cln = classesOrder[i];
728 initDb.add(pdslibFunc("registerClassMapping")+"("+toString(cln->Id)+", \""+cln->Name+"\");");
729 cln->generateContent();
733 void CDbNode::buildClassOrder(vector<CClassNode*>& classesOrder, vector<CFileNode*>& filesOrder)
735 set<CClassNode*> checkedClasses;
737 uint i;
739 for (i=0; i<ClassNodes.size(); ++i)
741 CClassNode *child = ClassNodes[i];
743 if (checkedClasses.find(child) != checkedClasses.end())
744 continue;
746 set<CClassNode*> beingChecked;
747 child->checkDependencies(beingChecked, checkedClasses, classesOrder);
750 set<CFileNode*> checkedFiles;
751 filesOrder.clear();
753 for (i=0; i<FileNodes.size(); ++i)
755 CFileNode *child = FileNodes[i];
757 if (checkedFiles.find(child) != checkedFiles.end())
758 continue;
760 set<CFileNode*> beingChecked;
761 child->checkDependencies(beingChecked, checkedFiles, filesOrder);
764 for (i=0; i<filesOrder.size(); ++i)
765 filesOrder[i]->Env = Env->nextArrayNode("files");
767 for (i=0; i<classesOrder.size(); ++i)
768 classesOrder[i]->Env = classesOrder[i]->getFileNode()->Env->nextArrayNode("classes");
772 void CDbNode::generateLogContent()
774 uint logid = 0;
776 uint i;
778 for (i=0; i<LogNodes.size(); ++i)
780 CLogMsgNode *child = LogNodes[i];
781 child->Id = logid;
782 logid += (uint)child->Logs.size();
784 child->generateContent();
788 // get file path from this file
789 string CDbNode::getFileNoExtPath(const std::string& file)
791 string thisPath = NLMISC::CFile::getPath(NLMISC::toLowerAscii(getDbFile()));
792 string filePath = NLMISC::CFile::getPath(NLMISC::toLowerAscii(file));
793 string fileName = NLMISC::CFile::getFilename(NLMISC::toLowerAscii(file));
795 if (thisPath == filePath)
796 return CFile::getFilenameWithoutExtension(fileName);
797 else
798 return CPath::standardizePath(filePath)+CFile::getFilenameWithoutExtension(NLMISC::toLowerAscii(file));
804 // File Node
805 bool CFileNode::prolog()
807 CDbNode* db = getDbNode();
808 db->FileNodes.push_back(this);
810 if (GenerateOnlyLogs)
811 Generate = false;
813 return true;
816 bool CFileNode::epilog()
818 return true;
821 bool CFileNode::generateProlog()
823 CDbNode* db = getDbNode();
825 if (!db->Description.empty())
826 Hpp << db->Description << "\n";
828 string filename = NLMISC::toLowerAscii(CFile::getFilenameWithoutExtension(Name));
830 setEnv("fullfilename", getFullStdPathNoExt(Name));
831 setEnv("filename", filename);
832 setEnv("headerfilename", strReplace(strupr(filename+".h"), ".", "_"));
833 setEnv("description", Description);
835 Hpp.setFileHeader(filename+".h", Description);
836 Cpp.setFileHeader(filename+".cpp", Description);
837 HppInline.setFileHeader(filename+"_inline.h", Description);
839 Hpp << "\n#ifndef " << strReplace(strupr(filename+".h"), ".", "_") << "\n";
840 Hpp << "#define " << strReplace(strupr(filename+".h"), ".", "_") << "\n\n";
843 Hpp << "#include <nel/misc/types_nl.h>\n";
844 Hpp << "#include <nel/misc/debug.h>\n";
845 Hpp << "#include <nel/misc/common.h>\n";
847 if (GenerateHAuto)
849 Hpp << "#include <nel/misc/hierarchical_timer.h>\n";
852 if (IncludeStandard)
854 define("incstd");
855 Hpp << "#include <nel/misc/entity_id.h>\n";
856 Hpp << "#include <nel/misc/sheet_id.h>\n";
859 Hpp << "#include <vector>\n";
860 Hpp << "#include <map>\n";
862 if (IncludePDSLib)
864 define("incpdslib");
865 Hpp << "#include <pd_lib/pd_lib.h>\n";
866 Hpp << "#include <game_share/persistent_data.h>\n";
868 Hpp << "\n";
870 if (SeparatedFlag)
872 string fullfile = getFullStdPathNoExt(db->MainFile.empty() ? db->Name : db->MainFile);
873 string filename = NLMISC::toLowerAscii(NLMISC::CFile::getFilenameWithoutExtension(fullfile));
874 Hpp << "#include \"" << filename << ".h\"\n";
875 Hpp << "\n";
878 Hpp << "// User #includes\n";
879 uint i;
880 for (i=0; i<IncludeNodes.size(); ++i)
882 Env->nextArrayNode("incuser")->set("as", IncludeNodes[i]->Name);
883 Hpp << "#include \"" << IncludeNodes[i]->Name << "\"\n";
886 Hpp << "\nnamespace " << db->Name << "\n{\n\n";
887 Hpp.unindent();
889 if (!db->Description.empty())
890 HppInline << db->Description;
891 HppInline << "namespace " << db->Name << "\n{\n\n";
892 HppInline.unindent();
893 Hpp << "//\n// Forward declarations\n//\n\n";
895 if (!db->Pch.empty())
897 Cpp << "\n";
898 Cpp << "#include \""+db->Pch+"\"";
901 Cpp << "\n";
902 if (SeparatedFlag || !IncludeDbFile)
904 Cpp << "#include \"" << filename << ".h\"\n";
906 else
908 Cpp << "#include \"" << getFileNoExtPath(getDbNode()->getDbFile()) << ".h\"\n";
911 Cpp << "\n";
912 Cpp << "namespace " << db->Name << "\n{\n\n";
913 Cpp.unindent();
915 return true;
918 bool CFileNode::generateEpilog()
920 CDbNode* db = getDbNode();
922 string fullfile = getFullStdPathNoExt(Name);
923 string filename = NLMISC::toLowerAscii(CFile::getFilenameWithoutExtension(Name));
925 Hpp.indent();
926 Hpp << "\n} // End of " << db->Name <<"\n";
928 if (!IncludeDbFile || SeparatedFlag)
930 // add inline #include
931 Hpp << "\n\n//\n// Inline implementations\n//\n\n";
932 Hpp << "#include \"" << filename << "_inline.h\"\n";
935 Hpp << "\n#endif\n";
937 HppInline.indent();
938 HppInline << "\n} // End of " << db->Name <<"\n";
940 Cpp.indent();
941 Cpp << "\n} // End of " << db->Name <<"\n";
943 if (Generate)
944 writeFile();
946 return true;
949 string CFileNode::getFileNoExtPath(const string& file)
951 string thisPath = NLMISC::CFile::getPath(NLMISC::toLowerAscii(Name));
952 string filePath = NLMISC::CFile::getPath(NLMISC::toLowerAscii(file));
953 string fileName = NLMISC::CFile::getFilename(NLMISC::toLowerAscii(file));
955 if (thisPath == filePath)
956 return CFile::getFilenameWithoutExtension(fileName);
957 else
958 return CFile::getFilenameWithoutExtension(NLMISC::toLowerAscii(file));
961 void CFileNode::writeFile()
963 string fullfile = getFullStdPathNoExt(Name);
965 Hpp.flush(fullfile+".h");
966 Cpp.flush(fullfile+".cpp");
967 HppInline.flush(fullfile+"_inline.h");
970 void CFileNode::checkDependencies(set<CFileNode*> &beingChecked,
971 set<CFileNode*> &checkedFiles,
972 vector<CFileNode*> &filesOrder)
974 if (beingChecked.find(this) != beingChecked.end())
975 error("circular dependency in file '"+Name+"'");
977 if (checkedFiles.find(this) != checkedFiles.end())
978 return;
980 beingChecked.insert(this);
981 checkedFiles.insert(this);
983 set<CFileNode*>::iterator it;
984 for (it=Dependencies.begin(); it!=Dependencies.end(); ++it)
986 CFileNode *fileNode = *it;
987 if (fileNode == this)
988 continue;
990 fileNode->checkDependencies(beingChecked, checkedFiles, filesOrder);
993 filesOrder.push_back(this);
1002 // Type Node
1003 bool CTypeNode::prolog()
1005 CDbNode* db = getDbNode();
1006 db->TypeNodes.push_back(this);
1008 return true;
1011 bool CTypeNode::generateContent()
1013 hOutput() << "/** " << Name << "\n";
1014 if (!Description.empty())
1016 hOutput() << Description << "\n";
1018 uint line, col;
1019 string file;
1020 getFileLine(line, col, file);
1021 hOutput() << "defined at " << file << ":" << line << "\n";
1022 hOutput() << "*/\n";
1024 hOutput() << "typedef " << getCppType() << " " << Name << ";\n\n";
1027 if (ToCppType != NULL)
1029 CCppCodeNode *tocpp = static_cast<CCppCodeNode*>(ToCppType);
1031 CFunctionGenerator toCppFunc;
1033 toCppFunc.init(storageToCpp());
1034 toCppFunc.setType(getName());
1035 toCppFunc.IsInline = true;
1036 toCppFunc.Proto = StorageType+" _v";
1038 toCppFunc.add(getName()+"\t__res;");
1039 toCppFunc.add(strReplace(strReplace(tocpp->RawCode, "$("+CppType+")", "__res"), "$("+StorageType+")", "_v"));
1040 toCppFunc.add("return __res;");
1041 toCppFunc.flush(hOutput(), cppOutput(), inlineOutput());
1043 if (ToStorageType != NULL)
1045 CCppCodeNode *tostorage = static_cast<CCppCodeNode*>(ToStorageType);
1047 CFunctionGenerator toStorageFunc;
1049 toStorageFunc.init(cppToStorage());
1050 toStorageFunc.setType(StorageType);
1051 toStorageFunc.IsInline = true;
1052 toStorageFunc.Proto = getName()+" _v";
1054 toStorageFunc.add(StorageType+"\t__res;");
1055 toStorageFunc.add(strReplace(strReplace(tostorage->RawCode, "$("+StorageType+")", "__res"), "$("+CppType+")", "_v"));
1056 toStorageFunc.add("return __res;");
1057 toStorageFunc.flush(hOutput(), cppOutput(), inlineOutput());
1060 hOutput() << "\n";
1062 return true;
1067 // Include Node
1068 bool CIncludeNode::prolog()
1070 CFileNode* file = getFileNode();
1071 file->IncludeNodes.push_back(this);
1072 return true;
1076 // Include Node
1077 bool CUsePchNode::prolog()
1079 CDbNode* db = getDbNode();
1080 db->Pch = Name;
1081 return true;
1085 // CppCode Node
1086 bool CCppCodeNode::prolog()
1088 return true;
1096 // Dimension Nodes
1097 bool CDimensionNode::prolog()
1099 CDbNode* db = getDbNode();
1100 db->TypeNodes.push_back(this);
1102 if (Dimension < 256)
1103 StorageType = "uint8";
1104 else if (Dimension < 65536)
1105 StorageType = "uint16";
1106 else
1107 StorageType = "uint32";
1109 CppType = "uint32";
1111 return true;
1114 bool CDimensionNode::epilog()
1116 return true;
1119 bool CDimensionNode::generateContent()
1121 hOutput() << "/** " << Name << "\n";
1122 if (!Description.empty())
1124 hOutput() << Description << "\n";
1126 uint line, col;
1127 string file;
1128 getFileLine(line, col, file);
1129 hOutput() << "defined at " << file << ":" << line << "\n";
1130 hOutput() << "*/\n";
1132 hOutput() << "typedef " << CppType << " " << Name << ";\n";
1133 hOutput() << "const " << getName() << "\t" << getSizeName() << " = " << Dimension << ";\n\n";
1135 return true;
1138 // Enum Nodes
1139 bool CEnumNode::prolog()
1141 CDbNode* db = getDbNode();
1142 db->TypeNodes.push_back(this);
1144 if (Name.empty() || Name[0] != 'T')
1145 error("enum name '"+Name+"' is invalid, must begin with a 'T'");
1147 CurrentValue = 0;
1148 CurrentEnum = Name;
1149 CurrentEnumNode = this;
1151 MinValue = 0;
1152 MaxValue = 0;
1154 return true;
1157 bool CEnumNode::epilog()
1159 uint i;
1161 for (i=0; i<Nodes.size(); ++i)
1163 CEnumNode *nd = dynamic_cast<CEnumNode*>(Nodes[i]);
1164 if (!nd)
1165 continue;
1166 Values.insert(Values.end(), nd->Values.begin(), nd->Values.end());
1169 for (i=0; i<Values.size(); ++i)
1171 if (MinValue > Values[i].second)
1172 MinValue = Values[i].second;
1173 if (MaxValue < Values[i].second)
1174 MaxValue = Values[i].second;
1177 CurrentEnumNode = NULL;
1178 return true;
1181 bool CEnumSimpleValueNode::prolog()
1183 CEnumNode *parent = dynamic_cast<CEnumNode*>(Parent);
1184 if (parent != NULL)
1186 CurrentValue = parent->CurrentValue;
1188 else
1190 CurrentValue = 0;
1192 uint i;
1193 for (i=0; i<Names.size(); ++i)
1195 CurrentEnumNode->Values.push_back(std::pair<string, uint32>(Names[i], CurrentValue));
1197 if (parent != NULL)
1198 ++(parent->CurrentValue);
1200 return true;
1203 bool CEnumSimpleValueNode::epilog()
1205 return true;
1208 bool CEnumRangeNode::prolog()
1210 CEnumNode *parent = dynamic_cast<CEnumNode*>(Parent);
1211 if (parent != NULL)
1213 CurrentValue = parent->CurrentValue;
1215 else
1217 CurrentValue = 0;
1220 CurrentEnumNode->Values.push_back(std::pair<string, uint32>(Name, CurrentValue));
1222 return true;
1225 bool CEnumRangeNode::epilog()
1227 CEnumNode *parent = dynamic_cast<CEnumNode*>(Parent);
1228 if (parent != NULL)
1230 parent->CurrentValue = CurrentValue;
1233 uint i;
1234 for (i=0; i<Nodes.size(); ++i)
1236 CEnumNode *nd = dynamic_cast<CEnumNode*>(Nodes[i]);
1237 if (!nd)
1238 continue;
1239 Values.insert(Values.end(), nd->Values.begin(), nd->Values.end());
1242 if (!EndRange.empty())
1244 CurrentEnumNode->Values.push_back(std::pair<string, uint32>(EndRange, CurrentValue));
1247 return true;
1251 bool CEnumNode::generateContent()
1253 hOutput() << "/** " << Name << "\n";
1254 if (!Description.empty())
1256 hOutput() << Description << "\n";
1258 uint line, col;
1259 string file;
1260 getFileLine(line, col, file);
1261 hOutput() << "defined at " << file << ":" << line << "\n";
1262 hOutput() << "*/\n";
1264 string enumTruncName = Name.substr(1);
1265 CClassGenerator gen;
1266 gen.init("C"+enumTruncName);
1267 gen.createPublic("enum", "Enum values", "");
1268 gen.createPublic("conv", "Conversion methods", "Use these methods to convert from enum value to string (and vice versa)");
1269 gen.createPrivate("init", "Enum initialisation", "");
1271 uint j;
1272 gen.addOther("enum "+Name+"\n", "enum");
1273 gen.addOther("{\n", "enum");
1274 for (j=0; j<Values.size(); ++j)
1275 gen.addOther(Values[j].first+" = "+toString(Values[j].second)+",\n", "enum");
1276 gen.addOther(getUnscopedUseSize()+" = "+toString(MaxValue-MinValue+1)+",\n", "enum");
1277 gen.addOther(getUnknownValue()+" = "+toString(MaxValue-MinValue+1)+",\n", "enum");
1278 if (!EndRange.empty())
1279 gen.addOther(EndRange+" = "+toString(MaxValue-MinValue+1)+",\n", "enum");
1280 gen.addOther("};\n", "enum");
1282 gen.startMethod("const std::string&", "toString", Name+" v", "conv", false, true, true);
1283 gen.add("if (v < 0 || v >= "+getUnscopedUseSize()+")");
1284 gen.add("{");
1285 gen.add("nlwarning(\""+Name+"::toString(): value '%u' is not matched, \\\"Unknown\\\" string returned\", v);");
1286 gen.add("return _UnknownString;");
1287 gen.add("}");
1288 //gen.add(checkCode("v"));
1289 gen.add("if (!_Initialised)");
1290 gen.add("{");
1291 gen.add("init();");
1292 gen.add("}");
1293 gen.add("return _StrTable[v];");
1295 gen.startMethod(getName(), "fromString", "const std::string& v", "conv", false, true, true);
1296 gen.add("if (!_Initialised)");
1297 gen.add("{");
1298 gen.add("init();");
1299 gen.add("}");
1300 gen.add("if(v==_UnknownString)");
1301 gen.add("{");
1302 gen.add("return Unknown;");
1303 gen.add("}");
1304 gen.add("const std::map<std::string, "+Name+">::const_iterator\tit = _ValueMap.find(NLMISC::toLowerAscii(v));");
1305 gen.add("if (it == _ValueMap.end())");
1306 gen.add("{");
1307 gen.add("nlwarning(\""+Name+"::toString(): string '%s' is not matched, 'Unknown' enum value returned\", v.c_str());");
1308 gen.add("return "+getUnknownValue()+";");
1309 gen.add("}");
1310 gen.add("return (*it).second;");
1313 gen.startMethod("void", "init", "", "init", false, false, true);
1314 gen.add("_StrTable.clear();");
1315 gen.add("_ValueMap.clear();");
1316 gen.add("_StrTable.resize("+toString(getSize()+1)+");");
1317 gen.add("uint\ti;");
1318 gen.add("for (i=0; i<"+toString(Values.size())+"; ++i)");
1319 gen.add("{");
1320 gen.add("_StrTable["+Name+"Convert[i].Value] = "+Name+"Convert[i].Name;");
1321 gen.add("_ValueMap[NLMISC::toLowerAscii(std::string("+Name+"Convert[i].Name))] = "+Name+"Convert[i].Value;");
1322 gen.add("}");
1324 gen.add("_Initialised = true;");
1327 gen.addAttribute("bool", "_Initialised", "init", true, "false");
1328 gen.addAttribute("std::string", "_UnknownString", "init", true, "\""+getUnknownValue()+"\"");
1329 gen.addAttribute("std::vector<std::string>", "_StrTable", "init", true);
1330 gen.addAttribute("std::map<std::string, "+Name+">", "_ValueMap", "init", true, "", false, "std::map<std::string, "+getName()+">");
1332 cppOutput() << "static const struct { char* Name; " << getName() << " Value; } " << Name << "Convert[] =\n";
1333 cppOutput() << "{\n";
1334 for (j=0; j<Values.size(); ++j)
1335 cppOutput() << "{ \"" << Values[j].first << "\", C"+enumTruncName+"::"+Values[j].first+" },\n";
1336 cppOutput() << "};\n";
1338 gen.flush(hOutput(), cppOutput(), inlineOutput());
1340 return true;
1347 // Class Node
1348 bool CClassNode::prolog()
1350 CDbNode* db = getDbNode();
1351 db->ClassNodes.push_back(this);
1353 return true;
1356 bool CClassNode::epilog()
1358 return true;
1361 string CClassNode::getUserCode(const string& name)
1363 uint i;
1364 for (i=0; i<Nodes.size(); ++i)
1366 CCppCodeNode *code = dynamic_cast<CCppCodeNode*>(Nodes[i]);
1367 if (!code)
1368 continue;
1370 if (code->Name == name)
1371 return code->RawCode;
1374 return "";
1378 void CClassNode::checkClassReferences()
1380 if (!Implements.empty())
1382 Gen.Inherit += (HasRowAccess ? string(", ") : string(""))+"public "+Implements;
1383 getDbNode()->Implemented.insert(Implements);
1387 if (!Inherited.empty())
1389 HasInheritance = true;
1390 CClassNode *nd = getClassNode(Inherited);
1391 nd->HasInheritance = true;
1392 nd->ChildrenClasses.push_back(Name);
1394 Dependencies.insert(nd);
1395 getFileNode()->Dependencies.insert(nd->getFileNode());
1398 CClassNode* inherit = this;
1399 while (inherit != NULL)
1401 if (MappedFlag)
1402 inherit->PDSMapped = true;
1404 inherit->Legacy.insert(this);
1405 inherit = getClassNode(inherit->Inherited, false);
1408 uint i;
1409 uint id = 0;
1410 for (i=0; i<Nodes.size(); ++i)
1412 CDeclarationNode *decl = dynamic_cast<CDeclarationNode*>(Nodes[i]);
1413 if (!decl)
1414 continue;
1416 decl->Id = id++;
1418 if (decl->ParentFlag)
1420 if (HasParent)
1421 decl->error("class '"+Name+"' already has a parent");
1423 //if (MappedFlag)
1424 // decl->error("class '"+Name+"' can't have a parent and be mapped at the same time");
1426 CClassNode* inherit = this;
1427 while (inherit != NULL)
1429 inherit->PDSMapped = false;
1430 inherit = getClassNode(inherit->Inherited, false);
1433 ParentClass = decl->ParentClass;
1434 HasParent = true;
1436 ParentIsHidden = decl->HiddenFlag;
1438 decl->getClassNode(decl->ParentClass)->IsBackReferenced = true;
1440 else if (decl->SetFlag)
1442 decl->getClassNode(decl->Type)->IsInSet = true;
1447 void CClassNode::fillAttributes()
1449 if (HasParent && !IsBackReferenced && !HasInheritance && !IsInSet && !DerivatedFlag && !MappedFlag)
1450 error("class '"+Name+"' has a parent whereas it is not backreferenced, has no inherited link and is not mapped");
1452 uint i;
1453 for (i=0; i<Nodes.size(); ++i)
1455 CDeclarationNode *decl = dynamic_cast<CDeclarationNode*>(Nodes[i]);
1456 if (!decl)
1457 continue;
1459 uint j;
1460 for (j=0; j<Nodes.size(); ++j)
1461 if (j != i && dynamic_cast<CDeclarationNode*>(Nodes[j]) != NULL && Nodes[j]->Name == decl->Name)
1462 decl->error("attribute '"+decl->Name+"' already defined");
1464 if (decl->ParentFlag)
1466 decl->DeclarationType = BackRef;
1468 else if (decl->ArrayFlag)
1470 CClassNode *classNd = NULL;
1471 CTypeNode *typeNd = NULL;
1473 if ( (classNd = decl->getClassNode(decl->Type, false)) )
1475 if (classNd->IsBackReferenced || classNd->ForceReference)
1477 if (decl->ForwardRefAttribute.empty())
1478 decl->error("no forward reference to parent in array declaration, class '"+decl->Type+"' is backref'd or has inheritance");
1480 classNd->IsInArrayRef = true;
1481 decl->IsRef = true;
1482 decl->DeclarationType = ArrayRef;
1484 if (classNd->ParentIsHidden)
1485 Dependencies.insert(classNd);
1487 else
1489 if (!decl->ForwardRefAttribute.empty())
1490 decl->error("forward reference declared whereas subclass is not backreferenced and has no inheritance link");
1492 Dependencies.insert(classNd);
1494 classNd->IsInArray = true;
1495 decl->IsRef = false;
1496 decl->DeclarationType = ArrayClass;
1499 else if ( (typeNd = decl->getTypeNode(decl->Type, false)) )
1501 decl->DeclarationType = ArrayType;
1503 else
1505 decl->error("type or class '"+decl->Type+"' not found");
1508 else if (decl->SetFlag)
1510 decl->IsRef = true;
1511 decl->DeclarationType = Set;
1513 else
1515 CClassNode *classNd = NULL;
1516 CTypeNode *typeNd = NULL;
1518 if ( (classNd = decl->getClassNode(decl->Type, false)) )
1520 if (classNd->IsBackReferenced || classNd->ForceReference)
1522 if (decl->ForwardRefAttribute.empty())
1523 decl->error("no forward reference to parent in array declaration, class '"+decl->Type+"' is backref'd or has inheritance");
1525 decl->IsRef = true;
1527 decl->DeclarationType = ForwardRef;
1529 else
1531 if (!decl->ForwardRefAttribute.empty())
1532 decl->error("forward reference declared whereas subclass is not backreferenced and has no inheritance link");
1534 Dependencies.insert(classNd);
1536 decl->IsRef = false;
1538 decl->DeclarationType = SimpleClass;
1541 else if ( (typeNd = decl->getTypeNode(decl->Type, false)) )
1543 decl->IsType = true;
1545 decl->DeclarationType = SimpleType;
1547 else
1549 decl->error("type or class '"+decl->Type+"' not found");
1554 CDeclarationNode *declNd = getClassKey();
1555 if (declNd != NULL)
1557 if (!declNd->IsType)
1558 error("attribute '"+declNd->Name+"' can't be a key, only simple type allowed");
1560 declNd->IsKey = true;
1564 void CClassNode::fillRefs()
1566 uint i;
1567 for (i=0; i<Nodes.size(); ++i)
1569 CDeclarationNode *decl = dynamic_cast<CDeclarationNode*>(Nodes[i]);
1570 if (!decl)
1571 continue;
1573 switch (decl->DeclarationType)
1575 case BackRef:
1577 // check parent is a valid class
1578 CClassNode *cln = decl->getClassNode(decl->ParentClass);
1579 CDeclarationNode *dln = dynamic_cast<CDeclarationNode*>(cln->getNode(decl->ParentField));
1580 if (!dln) decl->error("attribute '"+decl->ParentField+"' not found in class '"+decl->ParentClass+"'");
1582 if (!dln->ArrayFlag && !dln->SetFlag && !ForceReference)
1583 decl->error("back reference 'parent "+decl->ParentClass+":"+decl->ParentField+" "+decl->Name+"' is not forwarded in class '"+decl->ParentClass+"' with an array or a set");
1585 if (dln->Type != Name || dln->ForwardRefAttribute != decl->Name)
1586 decl->error("back reference 'parent "+decl->ParentClass+":"+decl->ParentField+" "+decl->Name+"' is not correctly forwarded in class '"+decl->ParentClass+"'");
1588 Friends.insert(cln->Name);
1590 break;
1592 case Set:
1594 CClassNode *cln = decl->getClassNode(decl->Type);
1595 CDeclarationNode *dln = dynamic_cast<CDeclarationNode*>(cln->getNode(decl->ForwardRefAttribute));
1596 if (!dln) decl->error("attribute '"+decl->ForwardRefAttribute+"' not found in class '"+decl->Type+"'");
1598 if (!dln->ParentFlag)
1599 decl->error("set '"+decl->Type+":"+decl->ForwardRefAttribute+"<> "+decl->Name+"' is not backref'd in class '"+decl->Type+"'");
1601 if (dln->ParentClass != Name || dln->ParentField != decl->Name)
1602 decl->error("set '"+decl->Type+":"+decl->ForwardRefAttribute+"<> "+decl->Name+"' is not correctly backref'd in class '"+decl->Type+"'");
1604 if (cln->getClassKey() == NULL)
1605 decl->error("class '"+decl->Type+"' has no key defined, whereas it is used in a set");
1607 cln->Friends.insert(Name);
1608 ForwardFriends.insert(cln->Name);
1610 break;
1612 case ArrayRef:
1614 if (decl->ForwardRefAttribute.empty())
1615 decl->error("No forward reference defined");
1617 CClassNode *cln = decl->getClassNode(decl->Type);
1618 CDeclarationNode *dln = dynamic_cast<CDeclarationNode*>(cln->getNode(decl->ForwardRefAttribute));
1619 CTypeNode *tln = decl->getTypeNode(decl->ArrayIndex);
1620 getFileNode()->Dependencies.insert(tln->getFileNode());
1621 if (!dln) decl->error("attribute '"+decl->ForwardRefAttribute+"' not found in class '"+decl->Type+"'");
1623 if (!dln->ParentFlag)
1624 decl->error("array '"+decl->Type+":"+decl->ForwardRefAttribute+"["+decl->ArrayIndex+"] "+decl->Name+"' is not backref'd in class '"+decl->Type+"'");
1626 if (dln->ParentClass != Name || dln->ParentField != decl->Name)
1627 decl->error("array '"+decl->Type+":"+decl->ForwardRefAttribute+"["+decl->ArrayIndex+"] "+decl->Name+"' is not correctly backref'd in class '"+decl->Type+"'");
1629 if (cln->getClassKey() == NULL)
1630 decl->error("class '"+decl->Type+"' has no key defined, whereas it is used in an array of ref");
1631 CDeclarationNode *kdn = dynamic_cast<CDeclarationNode*>(cln->getClassKey());
1632 if (!kdn) decl->error("attribute '"+cln->ClassKey+"' not found in class '"+cln->Name+"'");
1634 if (kdn->Type != decl->ArrayIndex)
1635 decl->error("type in array definition mismatch class '"+cln->Name+"' key definition");
1637 cln->Friends.insert(Name);
1638 ForwardFriends.insert(cln->Name);
1640 break;
1642 case ForwardRef:
1644 if (decl->ForwardRefAttribute.empty())
1645 decl->error("No forward reference defined");
1647 CClassNode *cln = decl->getClassNode(decl->Type);
1648 CDeclarationNode *dln = dynamic_cast<CDeclarationNode*>(cln->getNode(decl->ForwardRefAttribute));
1649 if (!dln) decl->error("attribute '"+decl->ForwardRefAttribute+"' not found in class '"+decl->Type+"'");
1651 if (!dln->ParentFlag)
1652 decl->error("set '"+decl->Type+":"+decl->ForwardRefAttribute+"<> "+decl->Name+"' is not backref'd in class '"+decl->Type+"'");
1654 if (dln->ParentClass != Name || dln->ParentField != decl->Name)
1655 decl->error("set '"+decl->Type+":"+decl->ForwardRefAttribute+"<> "+decl->Name+"' is not correctly backref'd in class '"+decl->Type+"'");
1657 cln->Friends.insert(Name);
1658 ForwardFriends.insert(cln->Name);
1660 break;
1662 case ArrayType:
1664 CTypeNode *tln = decl->getTypeNode(decl->ArrayIndex);
1665 getFileNode()->Dependencies.insert(tln->getFileNode());
1667 case SimpleType:
1668 break;
1670 case ArrayClass:
1672 CTypeNode *tln = decl->getTypeNode(decl->ArrayIndex);
1673 getFileNode()->Dependencies.insert(tln->getFileNode());
1675 case SimpleClass:
1677 CClassNode *cln = decl->getClassNode(decl->Type);
1678 cln->Friends.insert(Name);
1680 break;
1682 default:
1683 decl->error("Can't decide declaration type");
1684 break;
1689 void CClassNode::computeFriends()
1691 bool added;
1695 added = false;
1696 set<string>::iterator itf, itsf;
1698 for (itf=Friends.begin(); !added && itf!=Friends.end(); ++itf)
1700 CClassNode* pfriend = getClassNode(*itf);
1702 for (itsf=pfriend->Friends.begin(); !added && itsf!=pfriend->Friends.end(); ++itsf)
1704 const string& sfriend = *itsf;
1705 if (Friends.find(*itsf) == Friends.end())
1707 Friends.insert(*itsf);
1708 added = true;
1713 while (added);
1717 void CClassNode::checkDependencies(set<CClassNode*> &beingChecked,
1718 set<CClassNode*> &checkedClasses,
1719 vector<CClassNode*> &classesOrder)
1721 if (beingChecked.find(this) != beingChecked.end())
1722 error("circular dependency in class '"+Name+"'");
1724 if (checkedClasses.find(this) != checkedClasses.end())
1725 return;
1727 beingChecked.insert(this);
1728 checkedClasses.insert(this);
1730 set<CClassNode*>::iterator it;
1731 for (it=Dependencies.begin(); it!=Dependencies.end(); ++it)
1733 CClassNode *classNode = *it;
1735 classNode->checkDependencies(beingChecked, checkedClasses, classesOrder);
1738 classesOrder.push_back(this);
1743 void CClassNode::buildInit()
1745 CDbNode *db = getDbNode();
1747 if (!Init.empty())
1748 return;
1750 if (!Inherited.empty())
1752 CClassNode *mother = getClassNode(Inherited);
1753 if (mother)
1755 mother->buildInit();
1756 Init = mother->Init;
1758 uint i;
1759 for (i=0; i<Init.size(); ++i)
1761 if (!InitProto.empty())
1762 InitProto += ", ";
1763 if (!InitCallArgs.empty())
1764 InitCallArgs += ", ";
1766 CTypeNode* typeNode = getTypeNode(Init[i]->Type);
1767 InitProto += "const "+typeNode->getName()+" &"+Init[i]->Name;
1768 InitCallArgs += Init[i]->Name;
1773 if (!ClassKey.empty())
1775 CDeclarationNode *decl = dynamic_cast<CDeclarationNode*>(getNode(ClassKey));
1776 if (decl)
1778 Init.push_back(decl);
1780 if (!InitProto.empty())
1781 InitProto += ", ";
1783 CTypeNode* typeNode = getTypeNode(decl->Type);
1784 InitProto += "const "+typeNode->getName()+" &"+decl->Name;
1794 void CClassNode::computeAttributesColumns()
1796 if (Columns >= 0)
1797 return;
1799 CDbNode *db = getDbNode();
1801 Columns = 0;
1802 if (!Inherited.empty())
1804 CClassNode *mother = getClassNode(Inherited);
1805 mother->computeAttributesColumns();
1806 Columns = mother->Columns;
1808 Attributes = mother->Attributes;
1811 uint attribId = (uint)Attributes.size();
1812 uint i;
1813 for (i=0; i<Nodes.size(); ++i)
1815 CDeclarationNode *decl = dynamic_cast<CDeclarationNode*>(Nodes[i]);
1816 if (decl == NULL)
1817 continue;
1819 Attributes.push_back(decl);
1821 decl->Column = Columns;
1822 decl->Id = attribId++;
1823 CColumn col;
1825 // All for backref, set, forwardref, type
1826 switch (decl->DeclarationType)
1828 case ForwardRef:
1829 decl->Columns = 1;
1830 col.Name = decl->Name;
1831 col.Type = ForwardRef;
1832 col.TypeStr = "forwardref";
1833 col.TypeId = decl->getClassNode(decl->Type)->Id;
1834 col.ByteSize = 8;
1835 decl->ColumnList.push_back(col);
1836 break;
1837 case BackRef:
1838 decl->Columns = 1;
1839 col.Name = decl->Name;
1840 col.Type = BackRef;
1841 col.TypeStr = "backref";
1842 col.TypeId = decl->getClassNode(decl->ParentClass)->Id;
1843 col.ByteSize = 8;
1844 decl->ColumnList.push_back(col);
1845 break;
1846 case SimpleType:
1847 decl->Columns = 1;
1848 col.Name = decl->Name;
1849 col.Type = SimpleType;
1850 col.TypeStr = "type";
1851 col.TypeId = decl->getTypeNode(decl->Type)->Id;
1852 col.ByteSize = decl->getTypeNode(decl->Type)->Size;
1853 decl->ColumnList.push_back(col);
1854 break;
1855 case Set:
1856 decl->Columns = 1;
1857 col.Name = decl->Name;
1858 col.Type = Set;
1859 col.TypeStr = "set";
1860 col.TypeId = decl->getClassNode(decl->Type)->Id;
1861 col.ByteSize = 4;
1862 decl->ColumnList.push_back(col);
1863 break;
1864 case SimpleClass:
1866 CClassNode *sub = decl->getClassNode(decl->Type);
1867 sub->computeAttributesColumns();
1868 decl->Columns = sub->Columns;
1870 uint i, j;
1871 for (i=0; i<sub->Attributes.size(); ++i)
1873 CDeclarationNode *attrib = sub->Attributes[i];
1875 for (j=0; j<attrib->ColumnList.size(); ++j)
1877 col.Name = decl->Name+"."+attrib->ColumnList[j].Name;
1878 col.Type = attrib->ColumnList[j].Type;
1879 col.TypeStr = attrib->ColumnList[j].TypeStr;
1880 col.TypeId = attrib->ColumnList[j].TypeId;
1881 col.ByteSize = attrib->ColumnList[j].ByteSize;
1882 decl->ColumnList.push_back(col);
1886 break;
1887 case ArrayRef:
1889 CIndexNode *indexNd = decl->getIndexNode(decl->ArrayIndex);
1890 uint numInEnum = indexNd->getSize();
1891 decl->Columns = numInEnum;
1893 uint i;
1894 for (i=0; i<numInEnum; ++i)
1896 col.Name = decl->Name+"["+indexNd->getIndexName(i)+"]";
1897 col.Type = ForwardRef;
1898 col.TypeStr = "forwardref";
1899 col.TypeId = decl->getClassNode(decl->Type)->Id;
1900 col.ByteSize = 8;
1901 decl->ColumnList.push_back(col);
1904 break;
1905 case ArrayType:
1907 CIndexNode *indexNd = decl->getIndexNode(decl->ArrayIndex);
1908 uint numInEnum = indexNd->getSize();
1909 decl->Columns = numInEnum;
1911 uint i;
1912 for (i=0; i<numInEnum; ++i)
1914 col.Name = decl->Name+"["+indexNd->getIndexName(i)+"]";
1915 col.Type = SimpleType;
1916 col.TypeStr = "type";
1917 col.TypeId = decl->getTypeNode(decl->Type)->Id;
1918 col.ByteSize = decl->getTypeNode(decl->Type)->Size;
1919 decl->ColumnList.push_back(col);
1922 break;
1923 case ArrayClass:
1925 CIndexNode *indexNd = decl->getIndexNode(decl->ArrayIndex);
1927 CClassNode *sub = decl->getClassNode(decl->Type);
1928 sub->computeAttributesColumns();
1930 uint numInEnum = indexNd->getSize();
1931 decl->Columns = numInEnum*sub->Columns;
1933 uint i, j, k;
1934 for (k=0; k<numInEnum; ++k)
1936 for (i=0; i<sub->Attributes.size(); ++i)
1938 CDeclarationNode *attrib = sub->Attributes[i];
1940 for (j=0; j<attrib->ColumnList.size(); ++j)
1942 col.Name = decl->Name+"["+indexNd->getIndexName(k)+"]."+attrib->ColumnList[j].Name;
1943 col.Type = attrib->ColumnList[j].Type;
1944 col.TypeStr = attrib->ColumnList[j].TypeStr;
1945 col.TypeId = attrib->ColumnList[j].TypeId;
1946 col.ByteSize = attrib->ColumnList[j].ByteSize;
1947 decl->ColumnList.push_back(col);
1952 break;
1955 Columns += decl->Columns;
1963 bool CClassNode::generateContent()
1965 nlassert(Env != NULL);
1967 uint line, col;
1968 string file;
1969 getFileLine(line, col, file);
1971 setEnv("name", Name);
1972 if (!Description.empty())
1973 setEnv("description", Description);
1974 setEnv("deffile", file);
1975 setEnv("defline", line);
1977 computeAttributesColumns();
1979 uint j;
1982 // generate description
1984 hOutput() << "/** " << Name << "\n";
1985 if (!Description.empty())
1986 hOutput() << Description << "\n";
1988 hOutput() << "defined at " << file << ":" << line << "\n";
1989 hOutput() << "*/\n";
1991 CCppOutput& DbSummary = getDbNode()->DbSummary;
1992 DbSummary << "Class " << getDbNode()->Name << "::" << Name << ":\n";
1993 DbSummary << "----------------------------------------------------------\n";
1994 DbSummary << "located in file \"" << getFullStdPathNoExt(getFileNode()->Name) << ".h\"\n";
1995 DbSummary << "defined in file \"" << getFullStdPath(file) << "\"\n";
1996 DbSummary << "The class contains:\n\n";
1998 Gen.init(Name);
1999 Gen.createPublic("methods", "Accessors and Mutators methods", "Use these methods to change a value, add or delete elements.");
2000 Gen.createPublic("map", "Public Management methods", "Use these methods to create, load, unload and get\nan object from database.");
2001 Gen.createPublic("user", "User defined attributes and methods", "This code was verbatim copied from source file");
2002 Gen.createPublic("construct", "Public constructor", "This constructor is public to allow direct instanciation of the class");
2003 Gen.createPublic("persist", "Persistent methods declaration", "");
2004 Gen.createProtected("userinit", "User defined init and release methods", "Overload those methods to implement init and release behaviours");
2005 Gen.createProtected("attributes", "Attributes", "Don't modify those value manually, use accessors and mutators above");
2006 Gen.createProtected("internal", "Internal Management methods");
2007 Gen.createProtected("inherit map");
2008 Gen.createProtected("factories", "Default Factory and Fetch methods");
2009 Gen.createProtected("friends");
2011 // EGS Compat
2012 // -- begin
2014 Gen.startRaw("persist", false);
2015 ApplyId = Gen.startMethod("void", applyFunction, "CPersistentDataRecord &__pdr", "persist", false, inlineInternal, false, false, "", HasInheritance);
2016 StoreId = Gen.startMethod("void", storeFunction, "CPersistentDataRecord &__pdr", "persist", true, inlineInternal, false, false, "", HasInheritance);
2018 ClearId = Gen.startMethod("void", clearFunction, "", "map", false, inlineStaticPublic, false, false, "", HasInheritance);
2019 Gen.setDescription("Clear whole object content but key (delete subobjects if there are, key is left unmodified), default clear value is 0.");
2021 StoreId.add("uint16\t__Tok_MapKey = __pdr.addString(\"__Key__\");");
2022 StoreId.add("uint16\t__Tok_MapVal = __pdr.addString(\"__Val__\");");
2023 StoreId.add("uint16\t__Tok_ClassName = __pdr.addString(\"__Class__\");");
2024 ApplyId.add("uint16\t__Tok_MapKey = __pdr.addString(\"__Key__\");");
2025 ApplyId.add("uint16\t__Tok_MapVal = __pdr.addString(\"__Val__\");");
2026 ApplyId.add("uint16\t__Tok_ClassName = __pdr.addString(\"__Class__\");");
2028 if (!Inherited.empty())
2030 StoreId.add("uint16\t__Tok_Parent = __pdr.addString(\"__Parent__\");");
2031 ApplyId.add("uint16\t__Tok_Parent = __pdr.addString(\"__Parent__\");");
2034 for (j=0; j<Attributes.size(); ++j)
2036 CDeclarationNode* decl = Attributes[j];
2037 if (decl->Parent != this)
2038 continue;
2040 if (decl->DeclarationType == BackRef)
2042 ApplyId.add(decl->cppName()+" = NULL;");
2044 else
2046 StoreId.add("uint16\t"+decl->tokenName()+" = __pdr.addString(\""+decl->Name+"\");");
2047 ApplyId.add("uint16\t"+decl->tokenName()+" = __pdr.addString(\""+decl->Name+"\");");
2051 ApplyId.add("while (!__pdr.isEndOfStruct())");
2052 ApplyId.add("{");
2053 ApplyId.add( "if (false) {}");
2055 if (!Inherited.empty())
2057 StoreId.add("__pdr.pushStructBegin(__Tok_Parent);");
2058 StoreId.add(Inherited+"::store(__pdr);");
2059 StoreId.add("__pdr.pushStructEnd(__Tok_Parent);");
2061 ApplyId.add("else if (__pdr.peekNextToken() == __Tok_Parent)");
2062 ApplyId.add("{");
2063 ApplyId.add( "__pdr.popStructBegin(__Tok_Parent);");
2064 ApplyId.add( Inherited+"::apply(__pdr);");
2065 ApplyId.add( "__pdr.popStructEnd(__Tok_Parent);");
2066 ApplyId.add("}");
2069 // -- end
2072 for (j=0; j<Nodes.size(); ++j)
2074 CCppCodeNode* cpp = dynamic_cast<CCppCodeNode*>(Nodes[j]);
2075 if (cpp == NULL || !cpp->Name.empty())
2076 continue;
2078 Gen.addOther(cpp->RawCode, "user");
2081 HasRowAccess = false;
2082 HasTableAccess = false;
2084 if (!Inherited.empty())
2086 setEnv("inherit", Inherited);
2087 setEnv("inheritclass", Inherited);
2089 Gen.Inherit += "public "+Inherited;
2090 HasRowAccess = true;
2091 HasTableAccess = true;
2093 else if (HasInheritance || IsBackReferenced || IsInSet || ForceReference)
2095 setEnv("inherit", pdBaseDataName);
2097 Gen.Inherit += "public "+pdBaseDataName;
2098 HasTableAccess = true;
2099 HasRowAccess = true;
2102 if (Legacy.size() > 1 && HasTableAccess)
2104 CClassGenerator::SMethodId castId = Gen.startMethod(Name+"*", staticCastFunction, pdBaseDataName+"* obj", "map", false, inlineStaticPublic, true, false, "", false, false);
2105 Gen.setDescription("Cast base object to "+Name);
2106 castId.add("switch (obj->getTable())");
2107 castId.add("{");
2108 std::set<CClassNode*>::iterator itl;
2109 for (itl=Legacy.begin(); itl!=Legacy.end(); ++itl)
2111 CClassNode* child = (*itl);
2112 castId.add("case "+toString(child->Id)+":");
2114 castId.add("return static_cast<"+Name+"*>(obj);");
2115 castId.add("}");
2116 castId.add("return NULL;");
2118 CClassGenerator::SMethodId constCastId = Gen.startMethod("const "+Name+"*", staticConstCastFunction, "const "+pdBaseDataName+"* obj", "map", false, inlineStaticPublic, true, false, "", false, false);
2119 Gen.setDescription("Cast base object to const "+Name);
2120 constCastId.add("switch (obj->getTable())");
2121 constCastId.add("{");
2122 for (itl=Legacy.begin(); itl!=Legacy.end(); ++itl)
2124 CClassNode* child = (*itl);
2125 constCastId.add("case "+toString(child->Id)+":");
2127 constCastId.add("return static_cast<const "+Name+"*>(obj);");
2128 constCastId.add("}");
2129 constCastId.add("return NULL;");
2131 else if (Legacy.size() == 1 && HasTableAccess)
2133 CClassGenerator::SMethodId castId = Gen.startMethod(Name+"*", staticCastFunction, pdBaseDataName+"* obj", "map", false, inlineStaticPublic, true, false, "", false, false);
2134 std::set<CClassNode*>::iterator itl = Legacy.begin();
2135 Gen.setDescription("Cast base object to "+Name);
2136 castId.add("return (obj->getTable() == "+toString((*itl)->Id)+") ? static_cast<"+Name+"*>(obj) : NULL;");
2138 CClassGenerator::SMethodId constCastId = Gen.startMethod("const "+Name+"*", staticConstCastFunction, "const "+pdBaseDataName+"* obj", "map", false, inlineStaticPublic, true, false, "", false, false);
2139 Gen.setDescription("Cast base object to const "+Name);
2140 constCastId.add("return (obj->getTable() == "+toString((*itl)->Id)+") ? static_cast<const "+Name+"*>(obj) : NULL;");
2142 else
2146 if (HasRowAccess)
2147 define("hasrowaccess");
2148 if (HasTableAccess)
2149 define("hastableaccess");
2151 if (!Implements.empty())
2153 setEnv("implements", Implements);
2154 Gen.Inherit += (HasRowAccess ? string(", ") : string(""))+"public "+Implements;
2158 // generate init method
2160 buildInit();
2162 setEnv("initproto", InitProto);
2164 InitId = Gen.startMethod("void", initFunction, InitProto, "internal", false, inlineInternal, false, false, "", HasInheritance);
2165 if (!Inherited.empty())
2167 InitId.add(Inherited + "::" + initFunction + "(" + InitCallArgs + ");");
2168 setEnv("initcallargs", InitCallArgs);
2171 DestroyId = Gen.startMethod("void", destroyFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance);
2172 FetchId = Gen.startMethod("void", fetchFunction, CPDataName+" &data", "internal", false, inlineInternal, false, false, "", HasInheritance);
2173 RegisterId = Gen.startMethod("void", registerFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance);
2174 RegisterAttributesId = Gen.startMethod("void", registerAttributesFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance);
2175 UnregisterId = Gen.startMethod("void", unregisterFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance);
2176 UnregisterAttributesId = Gen.startMethod("void", unregisterAttributesFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance);
2177 SetParentId;
2178 SetUnnotifiedParentId;
2179 if (HasParent)
2181 SetParentId = Gen.startMethod("void", setParentFunction, ParentClass+"* __parent", "internal", false, inlineInternal);
2182 SetUnnotifiedParentId = Gen.startMethod("void", setUnnotifiedParentFunction, ParentClass+"* __parent", "internal", false, inlineInternal);
2185 if (HasRowAccess && GenerateDebugMessages)
2187 DestroyId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": destroy %u:%u\", "+getId()+", __BaseRow);");
2188 FetchId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": fetch %u:%u\", "+getId()+", __BaseRow);");
2191 if (!Inherited.empty())
2193 FetchId.add(Inherited+"::"+fetchFunction+"(data);");
2196 if (DerivatedFlag)
2198 UserInitId = Gen.startMethod("void", userInitFunction, "", "userinit", false, inlineUserInitDefaultCode, false, false, "", true);
2199 UserReleaseId = Gen.startMethod("void", userReleaseFunction, "", "userinit", false, inlineUserInitDefaultCode, false, false, "", true);
2202 NotifyInitId = Gen.startMethod("void", notifyInitFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance);
2203 string initUCode = getUserCode("onInit");
2204 if (!Inherited.empty())
2205 Gen.add(Inherited+"::"+notifyInitFunction+"();");
2206 if (DerivatedFlag)
2207 Gen.add(userInitFunction+"();");
2208 if (!initUCode.empty())
2210 Gen.add("{");
2211 uint line, col;
2212 string file;
2213 getFileLine(line, col, file);
2214 Gen.add("// "+Name+" init user code, defined at "+file+":"+toString(line));
2215 Gen.add(initUCode);
2216 Gen.add("}");
2219 NotifyReleaseId = Gen.startMethod("void", notifyReleaseFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance);
2220 string releaseUCode = getUserCode("onRelease");
2221 if (!releaseUCode.empty())
2223 Gen.add("{");
2224 uint line, col;
2225 string file;
2226 getFileLine(line, col, file);
2227 Gen.add("// "+Name+" release user code, defined at "+file+":"+toString(line));
2228 Gen.add(releaseUCode);
2229 Gen.add("}");
2231 if (DerivatedFlag)
2232 Gen.add(userReleaseFunction+"();");
2233 if (!Inherited.empty())
2234 Gen.add(Inherited+"::"+notifyReleaseFunction+"();");
2235 else if (HasRowAccess)
2236 Gen.add(pdslibFunc("release")+"("+getId()+", __BaseRow);");
2238 if (!Inherited.empty())
2240 DestroyId.add(Inherited+"::"+destroyFunction+"();");
2241 ClearId.add(Inherited+"::"+clearFunction+"();");
2245 // Generate XML description
2247 string xmlnode;
2248 xmlnode += "<classdef";
2249 xmlnode += " name='"+Name+"'";
2250 xmlnode += " id='"+toString(Id)+"'";
2251 if (!Inherited.empty())
2253 CClassNode *inh = getClassNode(Inherited);
2254 xmlnode += " inherit='"+toString(inh->Id)+"'";
2256 CDeclarationNode *dln = getClassKey();
2257 if (dln != NULL)
2259 xmlnode += " key='"+toString(dln->Id)+"'";
2261 if (MapClass && !MapClass->HasParent)
2263 xmlnode += " mapped='"+toString(MapClass->Id)+"'";
2265 if (HasRowAccess)
2268 if (!Reserve.empty())
2270 xmlnode += " allocate='"+(Reserve)+"'";
2272 else
2274 xmlnode += " allocate='10000'";
2278 xmlnode += " columns='"+toString(Columns)+"'";
2279 xmlnode += ">";
2280 getDbNode()->xmlDescription.push_back(xmlnode);
2282 indexUsedInInit = false;
2283 indexUsedInDestroy = false;
2284 indexUsedInFetch = false;
2285 tableAndRowIndicesUsedInFetch = false;
2286 indexUsedInRegister = false;
2287 indexUsedInUnregister = false;
2289 // generate code for init of new index
2290 if (HasRowAccess)
2292 RegisterId.add("__BaseRow = _IndexAllocator.allocate();");
2293 if (GenerateDebugMessages)
2295 if (MapClass != NULL)
2297 CDeclarationNode* key = MapClass->getKey();
2298 RegisterId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": register %u:%u, key="+key->displayPrintfPrefix()+"\", "+getId()+", __BaseRow, "+key->displayCppCode()+");");
2300 else
2302 RegisterId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": register %u:%u\", "+getId()+", __BaseRow);");
2306 string oeid;
2307 if (useEntityId())
2309 oeid = ", "+getClassKey()->cppName();
2312 RegisterId.add(pdslibFunc("allocateRow")+"("+getId()+", __BaseRow, "+(PDSMapped ? MapClass->getKey()->toUint64() : "0")+oeid+");");
2313 RegisterId.add(registerAttributesFunction + "();");
2315 RegisterAttributesId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": registerAttributes %u:%u\", "+getId()+", __BaseRow);");
2317 // send key to the pds (if key exists)
2318 if (!ClassKey.empty())
2320 CDeclarationNode *keyNode = getKey();
2321 CTypeNode *keyTypeNode = getTypeNode(keyNode->Type);
2322 ///// TYPE CAST
2323 RegisterAttributesId.add(pdslibFunc("set")+"("+getId()+", __BaseRow, ("+TColumnIndexName+")("+toString(keyNode->Column)+"), "+keyTypeNode->castToPDS(getKey()->cppName())+");");
2326 if (!Inherited.empty())
2328 RegisterAttributesId.add(Inherited + "::" + registerAttributesFunction + "();");
2331 UnregisterAttributesId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": unregisterAttributes %u:%u\", "+getId()+", __BaseRow);");
2333 if (!Inherited.empty())
2335 UnregisterAttributesId.add(Inherited + "::" + unregisterAttributesFunction + "();");
2338 if (HasParent)
2340 UnregisterAttributesId.add(setParentFunction+"(NULL);");
2343 if (GenerateDebugMessages)
2345 if (MapClass != NULL)
2347 CDeclarationNode* key = MapClass->getKey();
2348 UnregisterId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": unregister %u:%u, key="+key->displayPrintfPrefix()+"\", "+getId()+", __BaseRow, "+key->displayCppCode()+");");
2350 else
2351 UnregisterId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": unregister %u:%u\", "+getId()+", __BaseRow);");
2354 UnregisterId.add(unregisterAttributesFunction + "();");
2356 oeid.clear();
2357 if (useEntityId())
2359 oeid = ", "+getClassKey()->cppName();
2362 UnregisterId.add(pdslibFunc("deallocateRow")+"("+getId()+", __BaseRow"+oeid+");");
2363 UnregisterId.add("_IndexAllocator.deallocate(__BaseRow);");
2364 //UnregisterId.add(destroyFunction+"();");
2368 // add attributes and methods
2369 // - attributes are in private part
2370 // - read accessor are public
2371 // - write accessor are public or delegated in public accessor objects
2373 for (j=0; j<Nodes.size(); ++j)
2375 CDeclarationNode *dln = dynamic_cast<CDeclarationNode*>(Nodes[j]);
2376 if (!dln)
2377 continue;
2379 dln->Env = Env->nextArrayNode("dcl");
2381 dln->generateContent();
2385 uint columnId = 0;
2387 for (j=0; j<Attributes.size(); ++j)
2389 CDeclarationNode *dln = Attributes[j];
2390 getDbNode()->xmlDescription.push_back("<attribute "+dln->XmlNode+"/>");
2392 uint k;
2393 for (k=0; k<dln->ColumnList.size(); ++k)
2395 CColumn &column = dln->ColumnList[k];
2396 //getDbNode()->xmlDescription.push_back("<column id='"+toString(k)+"' name='"+column.Name+"' type='"+column.TypeStr+"' typeid='"+toString(column.TypeId)+"' size='"+toString(column.ByteSize)+"' columnid='"+toString(columnId)+"'/>");
2397 ++columnId;
2400 //getDbNode()->xmlDescription.push_back("</attribute>");
2403 getDbNode()->xmlDescription.push_back("</classdef>");
2405 if (HasTableAccess)
2407 Gen.startConstructor("", "construct");
2408 Gen.add("__BaseTable = "+toString(Id)+";");
2410 Gen.startDestructor("construct", true, DerivatedFlag || HasInheritance);
2413 // when inited/fetched a mapped class, map id to object
2414 if (MappedFlag)
2416 InitId.add("_Map["+getKey()->getFunc()+"()] = this;");
2417 FetchId.add("_Map["+getKey()->getFunc()+"()] = this;");
2418 DestroyId.add("_Map.erase("+getKey()->getFunc()+"());");
2422 // generate IPDBaseData API
2425 if (MappedFlag || DerivatedFlag || HasInheritance || ForceReference)
2427 if (DerivatedFlag)
2429 Gen.startMethod("void", staticSetUserFactoryFunction, TPDFactoryName+" userFactory", "map", false, inlineStaticPublic, true);
2430 Gen.setDescription("Set user factory for this class (as class is indicated as derived, a home made constructor must be provided)");
2431 Gen.add(staticInitFactoryFunction+"(userFactory);");
2434 Gen.startMethod("void", staticInitFactoryFunction, TPDFactoryName+" userFactory", "factories", false, inlineStaticInternal, true);
2435 Gen.add("if (!_FactoryInitialised)");
2436 Gen.add("{");
2437 Gen.add(pdslibFunc("registerClass")+"(" + toString(Id) + ", userFactory, "+staticFetchFunction+", "+((MappedFlag && !HasParent) ? staticNotifyLoadFailure : string("NULL"))+");");
2438 Gen.add("_FactoryInitialised = true;");
2439 Gen.add("}");
2441 Gen.addAttribute("bool", "_FactoryInitialised", "factories", true);
2443 if (MappedFlag || HasInheritance || ForceReference)
2446 // create: create an object, then init attributes and register
2449 Gen.startMethod(Name+"*", staticCreateFunction, InitProto, "map", false, inlineStaticPublic, true);
2450 Gen.setDescription("Create an object of the "+Name+" class, and declare it to the PDS.");
2451 if (GenerateDebugMessages)
2453 Gen.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": create\");");
2455 if (DerivatedFlag)
2457 Gen.add(Name + "\t*"+objectVariable+" = static_cast<" + Name + "*>("+pdslibFunc("create")+"("+toString(Id)+"));");
2459 else
2461 Gen.add(Name + "\t*"+objectVariable+" = static_cast<" + Name + "*>("+staticFactoryFunction+"());");
2464 string str = objectVariable+"->" + initFunction + "(";
2465 uint i;
2466 for (i=0; i<Init.size(); ++i)
2467 str += (i != 0 ? ", " : "") + Init[i]->Name;
2468 str += ");";
2469 Gen.add(str);
2470 Gen.add(objectVariable+"->" + registerFunction + "();");
2472 if (MappedFlag)
2474 Gen.add("_Map["+MapClass->ClassKey+"] = "+objectVariable+";");
2477 Gen.add(objectVariable+"->"+notifyInitFunction+"();");
2478 Gen.add("return "+objectVariable+";");
2481 if (MappedFlag)
2483 CDeclarationNode *dln = (MapClass != NULL ? MapClass->getKey() : NULL);
2484 CTypeNode *keyType = getTypeNode(dln->Type);
2486 // only authorize remove/load/unload for mapped objects that are roots
2487 if (!HasParent)
2489 Gen.startMethod("void", staticRemoveFunction, "const "+keyType->getName()+"& "+dln->Name, "map", false, inlineStaticPublic, true);
2490 Gen.setDescription("Destroy an object from the PDS. Caution! Object will no longer exist in database.\nAlso children (that is objects that belong to this object) are also destroyed.");
2491 if (GenerateDebugMessages)
2493 Gen.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": remove "+dln->displayPrintfPrefix()+"\", "+dln->displayCppCode(dln->Name)+");");
2495 Gen.add("std::map<" + keyType->getName() + "," + Name + "*>::iterator\tit = _Map.find("+dln->Name+");");
2496 Gen.add("if (it != _Map.end())");
2497 Gen.add("{");
2498 Gen.add(Name + "*\t__o = (*it).second;");
2499 Gen.add("__o->"+notifyReleaseFunction+"();");
2500 Gen.add("__o->"+unregisterFunction+"();");
2501 Gen.add("__o->"+destroyFunction+"();");
2502 Gen.add("delete __o;");
2503 //Gen.add("_Map.erase(it);");
2504 Gen.add("}");
2506 Gen.startMethod("void", staticLoadFunction, "const "+keyType->getName()+"& "+dln->Name, "map", false, inlineStaticPublic, true);
2507 Gen.setDescription("Retrieve an object from the database.\nData are sent asynchronously, so the load callback is called when data are ready.\nUse get() to access to the loaded object.");
2508 if (GenerateDebugMessages)
2510 Gen.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": load "+dln->displayPrintfPrefix()+"\", "+dln->displayCppCode(dln->Name)+");");
2512 Gen.add(pdslibFunc("load")+"("+toString(Id)+", "+dln->toUint64(dln->Name)+");");
2514 Gen.startMethod("void", staticSetLoadCbFunction, "void (*callback)(const "+keyType->getName()+"& key, "+Name+"* object)", "map", false, inlineStaticPublic, true);
2515 Gen.setDescription("Setup load callback so client is warned that load succeded or failed.");
2516 Gen.add(staticLoadCbAttribute+" = callback;");
2518 Gen.startMethod("void", staticNotifyLoadFailure, "uint64 key", "factories", false, inlineStaticInternal, true);
2519 Gen.add("if ("+staticLoadCbAttribute+" != NULL)");
2520 Gen.add("{");
2521 Gen.add(staticLoadCbAttribute+"("+keyType->castFromUser("key")+", NULL);");
2522 Gen.add("}");
2524 Gen.addAttribute("void", staticLoadCbAttribute, "factories", true, "NULL", true, "const "+keyType->getName()+"& key, "+Name+"* object");
2528 Gen.startMethod("void", staticUnloadFunction, "const " + keyType->getName() + " &" + dln->Name, "map", false, inlineStaticPublic, true);
2529 Gen.setDescription("Unload an object from the client memory. Object still exists in database and can be retrieved again using load.");
2530 if (GenerateDebugMessages)
2532 Gen.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": unload "+dln->displayPrintfPrefix()+"\", "+dln->displayCppCode(dln->Name)+");");
2534 Gen.add("std::map<" + keyType->getName() + "," + Name + "*>::iterator\tit = _Map.find("+dln->Name+");");
2535 Gen.add("if (it != _Map.end())");
2536 Gen.add("{");
2537 Gen.add(Name + "*\t__o = (*it).second;");
2538 Gen.add("__o->"+notifyReleaseFunction+"();");
2539 Gen.add("__o->"+destroyFunction+"();");
2540 Gen.add("delete __o;");
2541 //Gen.add("_Map.erase(it);");
2542 Gen.add("}");
2545 std::string mapType = "std::map<"+keyType->getName()+", "+Name+"*>";
2547 Gen.startMethod(Name+"*", staticGetFunction, "const " + keyType->getName() + " &" + dln->Name, "map", false, inlineStaticPublic, true);
2548 Gen.setDescription("Get an object in client. Object must have been previously loaded from database with a load.");
2549 if (GenerateDebugMessages)
2551 Gen.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": get "+dln->displayPrintfPrefix()+"\", "+dln->displayCppCode(dln->Name)+");");
2553 Gen.add(mapType+"::iterator\t__it = _Map.find("+dln->Name+");");
2554 if (GenerateDebugMessages)
2556 Gen.add("if (__it == _Map.end())");
2557 Gen.add("nlwarning(\""+Name+": unable to get %\"NL_I64\"u, not found in map.\", "+dln->toUint64(dln->Name)+");");
2559 Gen.add("return (__it != _Map.end()) ? (*__it).second : NULL;");
2561 Gen.startMethod(mapType+"::iterator", staticBeginFunction, "", "map", false, inlineStaticPublic, true);
2562 Gen.setDescription("Return the begin iterator of the global map of "+Name);
2563 Gen.add("return _Map.begin();");
2565 Gen.startMethod(mapType+"::iterator", staticEndFunction, "", "map", false, inlineStaticPublic, true);
2566 Gen.setDescription("Return the end iterator of the global map of "+Name);
2567 Gen.add("return _Map.end();");
2573 // generate internal management functions
2576 if (HasRowAccess || MappedFlag)
2578 if (MappedFlag)
2580 CDeclarationNode *dln = (MappedFlag ? getKey() : NULL);
2581 CTypeNode *keyType = getTypeNode(dln->Type);
2582 Gen.addAttribute("std::map<" + keyType->getName() + "," + Name + "*>", "_Map", "inherit map", true);
2585 Gen.addAttribute(indexAllocatorName, "_IndexAllocator", "factories", true);
2587 Gen.startMethod("void", staticInitFunction, "", "internal", false, inlineInternal, true, false, "", false);
2588 Gen.add(pdslibFunc("setIndexAllocator")+"("+toString(Id)+", _IndexAllocator);");
2589 if (MappedFlag || DerivatedFlag || HasInheritance || ForceReference)
2591 if (DerivatedFlag)
2593 // check factory has been set
2594 Gen.add("nlassertex(_FactoryInitialised, (\"User Factory for class "+Name+" not set!\"));");
2595 Gen.add("// factory must have been set by user before database init called!");
2596 Gen.add("// You must provide a factory for the class "+Name+" as it is marked as derived");
2597 Gen.add("// Call "+getDbNode()->Name+"::"+Name+"::"+staticSetUserFactoryFunction+"() with a factory before any call to "+getDbNode()->Name+"::init()!");
2599 else
2601 Gen.add(staticInitFactoryFunction+"("+staticFactoryFunction+");");
2605 getDbNode()->initDb.add(Name+"::"+staticInitFunction+"();");
2607 if (ForceReference)
2609 if (!DerivatedFlag) // forbid factory function for derivated classes
2611 Gen.startMethod(pdBaseDataName+"*", staticFactoryFunction, "", "factories", false, inlineStaticInternal, true);
2612 Gen.add("return new " + Name + "();");
2615 if (Inherited.empty())
2617 Gen.startMethod("void", staticFetchFunction, pdBaseDataName+" *object, "+CPDataName+" &data", "factories", false, inlineStaticInternal, true);
2618 Gen.add(Name + "\t*"+objectVariable+" = static_cast<" + Name + "*>(object);");
2619 Gen.add(objectVariable+"->"+fetchFunction+"(data);");
2620 if (MappedFlag)
2622 //Gen.add("_Map["+objectVariable+"->"+getKey()->getFunc()+"()] = "+objectVariable+";");
2623 if (!HasParent)
2625 Gen.add("if ("+staticLoadCbAttribute+" != NULL)");
2626 Gen.add("{");
2627 Gen.add(staticLoadCbAttribute+"("+objectVariable+"->"+getKey()->getFunc()+"(), "+objectVariable+");");
2628 Gen.add("}");
2631 Gen.add(objectVariable+"->"+notifyInitFunction+"();");
2636 // EGS Compat
2637 // -- begin
2639 ApplyId.add( "else");
2640 ApplyId.add( "{");
2641 ApplyId.add( "nlwarning(\"Skipping unrecognised token: %s\", __pdr.peekNextTokenName().c_str());");
2642 ApplyId.add( "__pdr.skipData();");
2643 ApplyId.add( "}");
2644 ApplyId.add("}");
2646 if (MappedFlag && !HasParent)
2648 ApplyId.add(notifyInitFunction+"();");
2652 //EGSImplId.add("\n#include \"game_share/persistent_data_template.h\"");
2653 //EGSImplId.add("#undef PERSISTENT_CLASS");
2654 //EGSImplId.add("#undef PERSISTENT_DATA");
2656 // -- end
2658 set<string>::iterator itf;
2659 for (itf=Friends.begin(); itf!=Friends.end(); ++itf)
2660 if (*itf != Name)
2661 Gen.addOther("friend class "+(*itf)+";\n", "friends");
2662 for (itf=ForwardFriends.begin(); itf!=ForwardFriends.end(); ++itf)
2663 if (*itf != Name)
2664 Gen.addOther("friend class "+(*itf)+";\n", "friends");
2665 Gen.addOther("friend class "+CPDSLibName+";\n", "friends");
2666 CDbNode* dbNode = getDbNode();
2667 Gen.addOther("friend void "+dbNode->Name+"::init(uint32);\n", "friends");
2669 Gen.flush(hOutput(), cppOutput(), inlineOutput());
2671 DbSummary << "\n\n";
2673 return true;
2676 void CClassNode::generateContentInCall(CCallContext *context)
2678 uint j;
2679 for (j=0; j<Nodes.size(); ++j)
2681 CDeclarationNode *dln = dynamic_cast<CDeclarationNode*>(Nodes[j]);
2682 if (!dln)
2683 continue;
2685 dln->generateContent(context);
2697 // Declaration Node
2698 bool CDeclarationNode::prolog()
2700 return true;
2703 bool CDeclarationNode::epilog()
2705 return true;
2710 void CDeclarationNode::generateContent(CCallContext *context)
2712 ClassNode = static_cast<CClassNode*>(Parent);
2714 nlassert(Env != NULL);
2716 setEnv("name", Name);
2718 XmlNode = "name='"+Name+"' id='"+toString(Id)+"' columnid='"+toString(Column)+"' columns='"+toString(Columns)+"'";
2720 if (context == NULL)
2722 CCppOutput& DbSummary = getDbNode()->DbSummary;
2723 DbSummary << "Attribute " << Name << ":\n";
2726 switch (DeclarationType)
2728 case SimpleType:
2729 generateTypeContent(context);
2730 break;
2732 case SimpleClass:
2733 generateClassContent(context);
2734 break;
2736 case BackRef:
2737 generateBackRefContent();
2738 break;
2740 case ForwardRef:
2741 generateForwardRefContent();
2742 break;
2744 case ArrayType:
2745 generateArrayTypeContent(context);
2746 break;
2748 case ArrayClass:
2749 generateArrayClassContent(context);
2750 break;
2752 case ArrayRef:
2753 generateArrayRefContent(context);
2754 break;
2756 case Set:
2757 generateSetContent(context);
2758 break;
2760 default:
2761 error("Can't decide declaration type");
2762 break;
2765 if (context == NULL)
2767 ClassNode->Gen.separator("methods");
2774 std::string CDeclarationNode::getAccessorName(CCallContext *context, const std::string& accessortype, const std::string& sep)
2776 return context->getRootCaller()->Name + sep +accessortype + context->getCallString();
2780 void CDeclarationNode::generateTypeContent(CCallContext *context)
2782 CClassGenerator& Gen = ClassNode->Gen;
2783 CCppOutput& DbSummary = getDbNode()->DbSummary;
2785 CClassGenerator::SMethodId &InitId = ClassNode->InitId;
2786 CClassGenerator::SMethodId &ClearId = ClassNode->ClearId;
2787 CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId;
2788 CClassGenerator::SMethodId &FetchId = ClassNode->FetchId;
2789 CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId;
2790 CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId;
2791 CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId;
2792 CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId;
2793 CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId;
2794 CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId;
2796 string UCodeContext;
2797 if (context != NULL)
2798 UCodeContext = context->getUserCodeContext();
2800 string onGetUser = getUserCode("onGet", UCodeContext);
2801 string onSetUser = getUserCode("onSet", UCodeContext);
2802 string onChangeUser = getUserCode("onChange", UCodeContext);
2804 CTypeNode *tnd = getTypeNode(Type);
2805 XmlNode += " type='type' typeid='"+toString(tnd->Id)+"'";
2807 setEnv("decltype", "type");
2808 setEnv("type", tnd->getName());
2809 define(IsKey, "iskey");
2810 setEnv("defaultvalue", tnd->getDefaultValue());
2811 setEnv("checkcode", tnd->checkCode(Name));
2813 CCallContext ctx(this);
2814 if (context != NULL)
2815 ctx = context->getSubContext(this);
2816 CClassGenerator &gen = ctx.getRootCaller()->Gen;
2818 // EGS Compat
2819 // -- begin
2821 CClassGenerator::SMethodId& StoreId = ClassNode->StoreId;
2822 CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId;
2825 ApplyId.add("else if (__pdr.peekNextToken() == "+tokenName()+")");
2826 ApplyId.add("{");
2827 tnd->generateApplyCode(ApplyId, tokenName(), cppName());
2828 ApplyId.add("}");
2830 tnd->generateStoreCode(StoreId, tokenName(), cppName());
2832 // -- end
2834 CTemplatizerEnv* env = ctx.getRootDeclaration()->Env->nextArrayNode("accessors");
2836 env->set("name", Name);
2837 env->set("type", tnd->getName());
2838 env->set("defaultvalue", tnd->getDefaultValue());
2839 env->set("checkcode", tnd->checkCode(Name));
2840 env->define(ctx.getRootCaller()->HasRowAccess, "rowaccess");
2841 env->define(IsKey, "iskey");
2842 env->set("rootcallerid", ctx.getRootCaller()->getId());
2843 env->set("callstr", ctx.getCallString());
2844 env->set("callargs", ctx.getCallArgList());
2845 env->set("callpath", ctx.getCallPath());
2846 env->set("column", ctx.getColumn());
2847 env->set("valuevar", valueVariable);
2848 env->set("castcpp", tnd->castToCpp(valueVariable));
2849 env->set("castpds", tnd->castToPDS(valueVariable));
2851 vector<string> checks = ctx.getCheckCode();
2852 for (uint i=0; i<checks.size(); ++i)
2853 env->nextArrayNode("checks")->set("check", checks[i]);
2854 env->nextArrayNode("checks")->set("check", tnd->checkCode(valueVariable));
2856 if (!onGetUser.empty()) env->set("onget", onGetUser);
2857 if (!onSetUser.empty()) env->set("onset", onSetUser);
2858 if (!onChangeUser.empty()) env->set("onchange", onChangeUser);
2861 // generate read accessor
2863 if (ctx.getRootCaller()->HasRowAccess)
2865 string arglist = ctx.getCallArgList();
2867 gen.startMethod(tnd->getName(), getFunctionPrefix+ctx.getCallString(), arglist, "methods", true, inlineAccessors);
2869 DbSummary << "\t" << getFunctionPrefix+ctx.getCallString() << "\n";
2871 uint i;
2872 vector<string> checks = ctx.getCheckCode();
2873 for (i=0; i<checks.size(); ++i)
2875 gen.add(checks[i]);
2878 if (!onGetUser.empty())
2880 gen.add("{");
2881 gen.add(onGetUser);
2882 gen.add("}");
2884 gen.add("return "+ctx.getCallPath()+";");
2888 // generate write accessor
2890 if (ctx.getRootCaller()->HasRowAccess && !IsKey)
2892 string arglist = ctx.getCallArgList();
2894 if (!arglist.empty())
2895 arglist += ", ";
2896 arglist += tnd->getName()+" "+valueVariable;
2897 gen.startMethod("void", setFunctionPrefix+ctx.getCallString(), appendArg(arglist, "bool forceWrite=false"), "methods", false, inlineAccessors);
2899 DbSummary << "\t" << setFunctionPrefix << ctx.getCallString() << "\n";
2901 if (GenerateHAuto)
2903 gen.add("H_AUTO("+getAccessorName(&ctx, setFunctionPrefix, "_")+")");
2906 if (VerboseMode)
2908 string verbStr;
2909 string callStr;
2911 verbStr = "nlinfo(\"" + ctx.getRootCaller()->Name + "(%d:%d)::" +setFunctionPrefix + ctx.getCallString() + "(";
2913 callStr = ctx.getDebugCallStringFmt();
2914 if (!callStr.empty())
2915 callStr += ", ";
2917 callStr += valueVariable+"="+tnd->getPrintfFmt();
2919 verbStr += callStr;
2920 verbStr += ")\", __BaseTable, __BaseRow, ";
2922 callStr = ctx.getDebugCallStringVal();
2923 if (!callStr.empty())
2924 callStr += ", ";
2926 callStr += tnd->getPrintfVal(valueVariable);
2928 verbStr += callStr;
2929 verbStr += ");";
2931 gen.add(verbStr);
2934 uint i;
2935 vector<string> checks = ctx.getCheckCode();
2936 for (i=0; i<checks.size(); ++i)
2938 gen.add(checks[i]);
2940 gen.add(tnd->checkCode(valueVariable));
2942 ///// TYPE CAST
2943 if (!onChangeUser.empty())
2945 gen.add("if ("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+")");
2946 gen.add("{");
2947 gen.add(onChangeUser);
2948 gen.add("}");
2950 if (!onSetUser.empty())
2952 gen.add("{");
2953 gen.add(onSetUser);
2954 gen.add("}");
2956 if (WriteTriggerFlag)
2958 gen.add("if (forceWrite && ("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+"))");
2960 else
2962 gen.add("if (("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+") || forceWrite)");
2964 gen.add("{");
2965 bool useEntityId = ctx.hasRootEntityIdKey();
2966 if (useEntityId)
2968 gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+", "+ctx.getRootCaller()->getKey()->cppName()+");");
2970 else
2972 gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+");");
2974 gen.add("}");
2975 gen.add(ctx.getCallPath()+" = "+tnd->castToCpp(valueVariable)+";");
2979 // generate attribute
2981 Gen.addAttribute(tnd->getName(), cppName(), "attributes");
2984 string defaultValue;
2985 if (!DefaultValue.empty())
2986 defaultValue = DefaultValue;
2987 else
2988 defaultValue = tnd->getDefaultValue();
2991 // generate init
2993 if (!IsKey)
2995 InitId.add(cppName()+" = "+defaultValue+";");
2997 else
2999 InitId.add(tnd->checkCode(Name));
3000 InitId.add(cppName()+" = "+Name+";");
3004 // generate create code
3009 // generate fetch code
3011 if (tnd->isEnum())
3012 FetchId.add("data.serialEnum("+cppName()+");");
3013 else if (tnd->CppType != tnd->StorageType)
3015 FetchId.add("{");
3016 FetchId.add(tnd->StorageType+"\t_v;");
3017 FetchId.add("data.serial(_v);");
3018 FetchId.add(cppName()+" = "+tnd->castToCpp("_v")+";");
3019 FetchId.add("}");
3021 else
3023 FetchId.add("data.serial("+cppName()+");");
3027 // generate clear code
3029 if (ctx.getRootCaller()->HasRowAccess && !IsKey)
3031 ctx.getRootCaller()->ClearId.add(ctx.getCallPath()+" = "+defaultValue+";");
3032 ctx.getRootCaller()->ClearId.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(defaultValue)+");");
3043 void CDeclarationNode::generateClassContent(CCallContext *context)
3045 setEnv("decltype", "class");
3047 CClassGenerator &Gen = ClassNode->Gen;
3048 CCppOutput& DbSummary = getDbNode()->DbSummary;
3050 CClassGenerator::SMethodId &InitId = ClassNode->InitId;
3051 CClassGenerator::SMethodId &ClearId = ClassNode->ClearId;
3052 CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId;
3053 CClassGenerator::SMethodId &FetchId = ClassNode->FetchId;
3054 CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId;
3055 CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId;
3056 CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId;
3057 CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId;
3058 CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId;
3059 CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId;
3061 CClassNode *cnd = getClassNode(Type);
3062 XmlNode += " type='class' classid='"+toString(cnd->Id)+"'";
3064 setEnv("type", Type);
3066 // EGS Compat
3067 // -- begin
3069 CClassGenerator::SMethodId& StoreId = ClassNode->StoreId;
3070 CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId;
3072 StoreId.add("__pdr.pushStructBegin("+tokenName()+");");
3073 StoreId.add(cppName()+".store(__pdr);");
3074 StoreId.add("__pdr.pushStructEnd("+tokenName()+");");
3076 ApplyId.add("else if (__pdr.peekNextToken() == "+tokenName()+")");
3077 ApplyId.add("{");
3078 ApplyId.add("__pdr.popStructBegin("+tokenName()+");");
3079 ApplyId.add(cppName()+".apply(__pdr);");
3080 ApplyId.add("__pdr.popStructEnd("+tokenName()+");");
3081 ApplyId.add("}");
3083 // -- end
3087 // export class accessors into root caller
3089 CCallContext ctx;
3090 if (context != NULL)
3091 ctx = *context;
3092 ctx.Context.push_back(this);
3093 cnd->generateContentInCall(&ctx);
3096 // generate attribute
3098 Gen.addAttribute(Type, cppName(), "attributes");
3101 // generate init
3103 InitId.add(cppName()+"."+initFunction+"();");
3106 // generate create code
3110 // generate fetch code
3112 FetchId.add(cppName()+"."+fetchFunction+"(data);");
3115 // generate clear code
3117 //ClearId.add(cppName()+"."+clearFunction+"();");
3125 void CDeclarationNode::generateBackRefContent()
3127 setEnv("decltype", "backref");
3128 define(HiddenFlag, "hidden");
3130 CClassGenerator &Gen = ClassNode->Gen;
3131 CCppOutput& DbSummary = getDbNode()->DbSummary;
3133 CClassGenerator::SMethodId &InitId = ClassNode->InitId;
3134 CClassGenerator::SMethodId &ClearId = ClassNode->ClearId;
3135 CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId;
3136 CClassGenerator::SMethodId &FetchId = ClassNode->FetchId;
3137 CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId;
3138 CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId;
3139 CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId;
3140 CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId;
3141 CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId;
3142 CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId;
3144 CClassNode *cnd = getClassNode(ParentClass);
3145 CDeclarationNode *dnd = cnd->getDeclarationNode(ParentField);
3146 CDeclarationNode *knd = (ClassNode->ClassKey.empty() ? NULL : ClassNode->getKey());
3147 XmlNode += " type='backref' classid='"+toString(cnd->Id)+"' backreferentid='"+toString(dnd->Id)+"'";
3148 if (knd != NULL)
3149 XmlNode += " key='"+toString(knd->Id)+"'";
3151 setEnv("type", ParentClass);
3154 // generate read accessor
3156 Gen.startMethod(ParentClass+"*", getFunc(), "", "methods", false, inlineAccessors);
3157 Gen.add("return "+cppName()+";");
3159 Gen.startMethod("const "+ParentClass+"*", getFunc(), "", "methods", true, inlineAccessors);
3160 Gen.add("return "+cppName()+";");
3162 DbSummary << "\t" << getFunc() << "\n";
3165 // generate write accessor
3169 // generate attribute
3171 Gen.addAttribute(ParentClass+"*", cppName(), "attributes");
3174 // generate init
3176 InitId.add(cppName()+" = NULL;");
3179 // generate create code
3183 // generate fetch code
3185 FetchId.add(cppName()+" = NULL;");
3188 // generate set parent code
3191 bool useId = ClassNode->useEntityId();
3192 bool parentUseId = cnd->useEntityId();
3194 if (parentUseId)
3195 SetParentId.add("NLMISC::CEntityId\tprevId;");
3197 if (!HiddenFlag)
3199 //SetParentId.add(pdslibFunc("set")+"("+ClassNode->getId()+", getRow(), ("+TColumnIndexName+")("+toString(Column)+"), (__parent != NULL ? "+objectIndexName+"("+(cnd->HasInheritance ? toString("__parent->getTable()") : toString(cnd->Id))+", __parent->getRow()) : "+nullIndexName+"));");
3201 SetParentId.add("if ("+cppName()+" != NULL)");
3202 SetParentId.add("{");
3204 if (parentUseId)
3205 SetParentId.add("prevId = "+cppName()+"->"+getFunctionPrefix+cnd->getKey()->Name+"();");
3207 if (ClassNode->getClassKey() == NULL)
3209 SetParentId.add(cppName()+"->"+dnd->unlinkFunc()+"();");
3211 else
3213 SetParentId.add(cppName()+"->"+dnd->unlinkFunc()+"("+ClassNode->getKey()->cppName()+");");
3215 SetParentId.add("}");
3217 else
3219 if (parentUseId)
3221 SetParentId.add("if ("+cppName()+" != NULL)");
3222 SetParentId.add("{");
3223 SetParentId.add("prevId = "+cppName()+"->"+cnd->getKey()->cppName()+";");
3224 SetParentId.add("}");
3228 string oeid;
3229 string peid;
3231 if (useId)
3232 oeid = ", "+ClassNode->getKey()->cppName();
3234 if (parentUseId)
3235 peid = ", ("+cppName()+" != NULL ? "+cppName()+"->"+getFunctionPrefix+cnd->getKey()->Name+"() : NLMISC::CEntityId::Unknown), prevId";
3237 SetParentId.add(cppName()+" = __parent;");
3238 SetParentId.add(pdslibFunc("setParent")+"("+ClassNode->getId()+", getRow(), ("+TColumnIndexName+")("+toString(Column)+"), (__parent != NULL ? "+objectIndexName+"("+(cnd->HasInheritance ? toString("__parent->getTable()") : toString(cnd->Id))+", __parent->getRow()) : "+nullIndexName+")"+oeid+peid+");");
3240 SetUnnotifiedParentId.add(cppName()+" = __parent;");
3249 void CDeclarationNode::generateClassPtrApplyCode(const std::string& value)
3251 CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId;
3253 ApplyId.add(value+" = NULL;");
3254 ApplyId.add("if (__pdr.peekNextToken() == __Tok_ClassName)");
3255 ApplyId.add("{");
3256 ApplyId.add( "std::string\t__className;");
3257 ApplyId.add( "__pdr.pop(__Tok_ClassName, __className);");
3258 ApplyId.add( value+" = "+Type+"::cast("+pdslibFunc("create")+"(__className));");
3259 ApplyId.add( "if ("+value+" != NULL)");
3260 ApplyId.add( "{");
3261 ApplyId.add( "__pdr.popStructBegin("+tokenName()+");");
3262 ApplyId.add( value+"->apply(__pdr);");
3263 ApplyId.add( value+"->"+setUnnotifiedParentFunction+"(this);");
3264 ApplyId.add( "__pdr.popStructEnd("+tokenName()+");");
3265 ApplyId.add( "}");
3266 ApplyId.add( "else");
3267 ApplyId.add( "{");
3268 ApplyId.add( "__pdr.skipStruct();");
3269 ApplyId.add( "}");
3270 ApplyId.add("}");
3273 void CDeclarationNode::generateClassPtrStoreCode(const std::string& value)
3275 CClassGenerator::SMethodId& StoreId = ClassNode->StoreId;
3277 StoreId.add("if ("+value+" != NULL)");
3278 StoreId.add("{");
3279 StoreId.add( "std::string\t__className = "+pdslibFunc("getClassName")+"("+value+");");
3280 StoreId.add( "__pdr.push(__Tok_ClassName, __className);");
3281 StoreId.add( "__pdr.pushStructBegin("+tokenName()+");");
3282 StoreId.add( value+"->store(__pdr);");
3283 StoreId.add( "__pdr.pushStructEnd("+tokenName()+");");
3284 StoreId.add("}");
3289 void CDeclarationNode::generateForwardRefContent()
3291 setEnv("decltype", "forwardref");
3293 CClassGenerator &Gen = ClassNode->Gen;
3294 CCppOutput& DbSummary = getDbNode()->DbSummary;
3296 CClassGenerator::SMethodId &InitId = ClassNode->InitId;
3297 CClassGenerator::SMethodId &ClearId = ClassNode->ClearId;
3298 CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId;
3299 CClassGenerator::SMethodId &FetchId = ClassNode->FetchId;
3300 CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId;
3301 CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId;
3302 CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId;
3303 CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId;
3304 CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId;
3305 CClassGenerator::SMethodId &NotifyInitId = ClassNode->NotifyInitId;
3306 CClassGenerator::SMethodId &NotifyReleaseId = ClassNode->NotifyReleaseId;
3308 CClassNode *cnd = getClassNode(Type);
3309 CDeclarationNode *dnd = cnd->getDeclarationNode(ForwardRefAttribute);
3310 CDeclarationNode *knd = (cnd->ClassKey.empty() ? NULL : cnd->getKey());
3311 XmlNode += " type='forwardref' classid='"+toString(cnd->Id)+"' forwardreferedid='"+toString(dnd->Id)+"'";
3312 if (knd != NULL)
3313 XmlNode += " key='"+toString(knd->Id)+"'";
3315 setEnv("type", Type);
3317 // EGS Compat
3318 // -- begin
3320 CClassGenerator::SMethodId& StoreId = ClassNode->StoreId;
3321 CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId;
3323 StoreId.add("// store "+Name);
3324 StoreId.add("__pdr.pushStructBegin("+tokenName()+");");
3325 generateClassPtrStoreCode(cppName());
3326 StoreId.add("__pdr.pushStructEnd("+tokenName()+");");
3328 ApplyId.add("// apply "+Name);
3329 ApplyId.add("else if (__pdr.peekNextToken() == "+tokenName()+")");
3330 ApplyId.add("{");
3331 ApplyId.add( "__pdr.popStructBegin("+tokenName()+");");
3332 generateClassPtrApplyCode(cppName());
3333 ApplyId.add( "__pdr.popStructEnd("+tokenName()+");");
3334 ApplyId.add("}");
3336 // -- end
3340 // generate read accessor
3342 Gen.startMethod(Type+"*", getFunc(), "", "methods", false, inlineAccessors);
3343 Gen.add("return "+cppName()+";");
3345 Gen.startMethod("const "+Type+"*", getFunc(), "", "methods", true, inlineAccessors);
3346 Gen.add("return "+cppName()+";");
3348 DbSummary << "\t" << getFunc() << "\n";
3351 // generate write accessor
3353 Gen.startMethod("void", setFunc(), Type+"* "+valueVariable, "methods", false, inlineAccessors);
3354 Gen.add("if ("+cppName()+" != NULL)");
3355 Gen.add("{");
3356 Gen.add(cppName()+"->"+setParentFunction+"(NULL);");
3357 Gen.add("}");
3358 Gen.add(valueVariable+"->"+setParentFunction+"(this);");
3359 Gen.add(cppName()+" = "+valueVariable+";");
3361 DbSummary << "\t" << setFunc() << "\n";
3364 // generate attribute
3366 Gen.addAttribute(Type+"*", cppName(), "attributes");
3369 // generate init
3371 InitId.add(cppName()+" = NULL;");
3374 // generate destroy code
3376 DestroyId.add("if ("+cppName()+" != NULL)");
3377 DestroyId.add("{");
3378 DestroyId.add(Type+"*\t__o = "+cppName()+";");
3379 DestroyId.add("__o->"+destroyFunction+"();");
3380 DestroyId.add("delete __o;");
3381 DestroyId.add("}");
3384 // generate create code
3388 // generate fetch code
3390 FetchId.add("// read table and row, create an object, affect to the ref, and fetch it");
3391 if (!ClassNode->tableAndRowIndicesUsedInFetch)
3393 FetchId.add(TTableIndexName+"\ttableIndex;\n"+TRowIndexName+"\trowIndex;");
3394 ClassNode->tableAndRowIndicesUsedInFetch = true;
3396 FetchId.add(cppName()+" = NULL;");
3397 FetchId.add("data.serial(tableIndex, rowIndex);");
3398 FetchId.add("if (rowIndex != "+INVALID_ROW_INDEXName+" && tableIndex != "+INVALID_TABLE_INDEXName+")");
3399 FetchId.add("{");
3400 FetchId.add(cppName()+" = static_cast<"+Type+"*>("+pdslibFunc("create")+"(tableIndex));");
3401 FetchId.add(pdslibFunc("setRowIndex")+"(rowIndex, "+cppName()+");");
3402 FetchId.add(cppName()+"->"+fetchFunction+"(data);");
3403 FetchId.add(cppName()+"->"+setUnnotifiedParentFunction+"(this);");
3404 FetchId.add("}");
3407 // generate register/unregister code
3410 UnregisterAttributesId.add("if ("+cppName()+" != NULL)");
3411 UnregisterAttributesId.add("{");
3412 UnregisterAttributesId.add(Type+"*\t"+objectVariable+" = "+cppName()+";");
3413 UnregisterAttributesId.add(objectVariable+"->"+unregisterFunction+"();");
3414 UnregisterAttributesId.add(objectVariable+"->"+destroyFunction+"();");
3415 UnregisterAttributesId.add("delete "+objectVariable+";");
3416 UnregisterAttributesId.add("}");
3419 // generate init/release notification
3422 NotifyInitId.add("if ("+cppName()+" != NULL)");
3423 NotifyInitId.add("{");
3424 NotifyInitId.add(cppName()+"->"+notifyInitFunction+"();");
3425 NotifyInitId.add("}");
3427 NotifyReleaseId.add("if ("+cppName()+" != NULL)");
3428 NotifyReleaseId.add("{");
3429 NotifyReleaseId.add(cppName()+"->"+notifyReleaseFunction+"();");
3430 NotifyReleaseId.add("}");
3433 // generate unlink code
3435 string unlinkProto;
3436 if (cnd->getClassKey() != NULL)
3438 CDeclarationNode* kd = cnd->getClassKey();
3439 CTypeNode* keyType = getTypeNode(kd->Type);
3440 unlinkProto = keyType->getName()+" dummy";
3442 Gen.startMethod("void", unlinkFunc(), unlinkProto, "internal", false, inlineInternal);
3443 Gen.add("{");
3444 Gen.add(cppName()+" = NULL;");
3445 Gen.add("}");
3448 // generate clear code
3450 //ClearId.add(cppName()+"->"+setParentFunction+"(NULL);");
3451 ClearId.add(Type+"*\t"+objectVariable+" = "+cppName()+";");
3452 ClearId.add(objectVariable+"->"+unregisterFunction+"();");
3453 ClearId.add(objectVariable+"->"+destroyFunction+"();");
3454 ClearId.add("delete "+objectVariable+";");
3459 void CDeclarationNode::generateArrayApplyCode()
3461 CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId;
3463 ApplyId.add("// apply "+Name);
3464 ApplyId.add("else if (__pdr.peekNextToken() == "+tokenName()+")");
3465 ApplyId.add("{");
3466 ApplyId.add( "__pdr.popStructBegin("+tokenName()+");");
3467 ApplyId.add( "uint\tindex = 0;");
3468 ApplyId.add( "while (!__pdr.isEndOfStruct())");
3469 ApplyId.add( "{");
3471 CIndexNode *ind = getIndexNode(ArrayIndex);
3472 if (ind->isEnum())
3474 ApplyId.add("std::string\tindexname;");
3475 ApplyId.add("__pdr.pop(__Tok_MapKey, indexname);");
3476 ApplyId.add("index = "+ind->getFromStringCode("indexname")+";");
3480 void CDeclarationNode::generateArrayStoreCode()
3482 CClassGenerator::SMethodId& StoreId = ClassNode->StoreId;
3484 StoreId.add("// store "+Name);
3485 StoreId.add("__pdr.pushStructBegin("+tokenName()+");");
3486 CIndexNode *ind = getIndexNode(ArrayIndex);
3488 StoreId.add("for (uint index=0; index<"+ind->getSizeName()+"; ++index)");
3489 StoreId.add("{");
3491 if (ind->isEnum())
3493 StoreId.add("std::string\tindexname = "+ind->getToStringCode(ind->castFromUser("index"))+";");
3494 StoreId.add("__pdr.push(__Tok_MapKey, indexname);");
3499 void CDeclarationNode::generateArrayEndCode()
3501 CClassGenerator::SMethodId& StoreId = ClassNode->StoreId;
3502 CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId;
3504 ApplyId.add( "++index;");
3505 ApplyId.add( "}");
3506 ApplyId.add( "__pdr.popStructEnd("+tokenName()+");");
3507 ApplyId.add("}");
3509 StoreId.add("}");
3510 StoreId.add("__pdr.pushStructEnd("+tokenName()+");");
3515 void CDeclarationNode::generateArrayTypeContent(CCallContext *context)
3517 setEnv("decltype", "arraytype");
3519 CClassGenerator &Gen = ClassNode->Gen;
3520 CCppOutput& DbSummary = getDbNode()->DbSummary;
3522 CClassGenerator::SMethodId &InitId = ClassNode->InitId;
3523 CClassGenerator::SMethodId &ClearId = ClassNode->ClearId;
3524 CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId;
3525 CClassGenerator::SMethodId &FetchId = ClassNode->FetchId;
3526 CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId;
3527 CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId;
3528 CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId;
3529 CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId;
3530 CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId;
3531 CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId;
3533 string UCodeContext;
3534 if (context != NULL)
3535 UCodeContext = context->getUserCodeContext();
3537 string onGetUser = getUserCode("onGet", UCodeContext);
3538 string onSetUser = getUserCode("onSet", UCodeContext);
3539 string onChangeUser = getUserCode("onChange", UCodeContext);
3541 CTypeNode *tnd = getTypeNode(Type);
3542 CIndexNode *ind = getIndexNode(ArrayIndex);
3543 XmlNode += " type='arraytype' typeid='"+toString(tnd->Id)+"' indexid='"+toString(ind->Id)+"'";
3545 CCallContext ctx(this);
3546 if (context != NULL)
3547 ctx = context->getSubContext(this);
3548 CClassGenerator &gen = ctx.getRootCaller()->Gen;
3550 setEnv("type", tnd->getName());
3551 setEnv("indexsize", ind->getSizeName());
3553 // EGS Compat
3554 // -- begin
3556 CClassGenerator::SMethodId& StoreId = ClassNode->StoreId;
3557 CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId;
3559 generateArrayApplyCode();
3560 generateArrayStoreCode();
3562 ApplyId.add(tnd->getName()+"\tvalue;");
3563 tnd->generateApplyCode(ApplyId, "__Tok_MapVal", "value");
3564 ApplyId.add("if (index != "+toString(ind->getSize())+")");
3565 ApplyId.add("{");
3566 ApplyId.add( cppName()+"[index] = value;");
3567 ApplyId.add("}");
3569 tnd->generateStoreCode(ApplyId, "__Tok_MapVal", cppName()+"[index]");
3571 generateArrayEndCode();
3573 // -- end
3577 // generate read accessor
3579 if (ctx.getRootCaller()->HasRowAccess)
3581 string arglist = ctx.getCallArgList();
3582 ctx.getRootCaller()->Gen.startMethod(tnd->getName(), getFunctionPrefix+ctx.getCallString(), arglist, "methods", true, inlineAccessors);
3584 DbSummary << "\t" << getFunctionPrefix+ctx.getCallString() << "\n";
3586 uint i;
3587 vector<string> checks = ctx.getCheckCode();
3588 for (i=0; i<checks.size(); ++i)
3589 gen.add(checks[i]);
3591 if (!onGetUser.empty())
3593 gen.add("{");
3594 gen.add(onGetUser);
3595 gen.add("}");
3597 gen.add("return "+ctx.getCallPath()+";");
3601 // generate write accessor
3603 if (ctx.getRootCaller()->HasRowAccess)
3605 string arglist = ctx.getCallArgList();
3606 if (!arglist.empty())
3607 arglist += ", ";
3608 arglist += tnd->getName()+" "+valueVariable;
3609 gen.startMethod("void", setFunctionPrefix+ctx.getCallString(), appendArg(arglist, "bool forceWrite=false"), "methods", false, inlineAccessors);
3611 DbSummary << "\t" << setFunctionPrefix+ctx.getCallString() << "\n";
3613 if (GenerateHAuto)
3615 gen.add("H_AUTO("+getAccessorName(&ctx, getFunctionPrefix, "_")+")");
3618 if (VerboseMode)
3620 string verbStr;
3621 string callStr;
3623 verbStr = "nlinfo(\"" + ctx.getRootCaller()->Name + "(%d:%d)::" +setFunctionPrefix + ctx.getCallString() + "(";
3625 callStr = ctx.getDebugCallStringFmt();
3626 if (!callStr.empty())
3627 callStr += ", ";
3629 callStr += valueVariable+"="+tnd->getPrintfFmt();
3631 verbStr += callStr;
3632 verbStr += ")\", __BaseTable, __BaseRow, ";
3634 callStr = ctx.getDebugCallStringVal();
3635 if (!callStr.empty())
3636 callStr += ", ";
3638 callStr += tnd->getPrintfVal(valueVariable);
3640 verbStr += callStr;
3641 verbStr += ");";
3643 gen.add(verbStr);
3646 uint i;
3647 vector<string> checks = ctx.getCheckCode();
3648 for (i=0; i<checks.size(); ++i)
3649 gen.add(checks[i]);
3650 gen.add(tnd->checkCode(valueVariable));
3652 if (!onChangeUser.empty())
3654 gen.add("if ("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+")");
3655 gen.add("{");
3656 gen.add(onChangeUser);
3657 gen.add("}");
3659 if (!onSetUser.empty())
3661 gen.add("{");
3662 gen.add(onGetUser);
3663 gen.add("}");
3665 if (WriteTriggerFlag)
3667 gen.add("if (forceWrite && ("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+"))");
3669 else
3671 gen.add("if (("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+") || forceWrite)");
3673 gen.add("{");
3674 bool useEntityId = ctx.hasRootEntityIdKey();
3675 if (useEntityId)
3677 gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+", "+ctx.getRootCaller()->getKey()->cppName()+");");
3679 else
3681 gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+");");
3683 //gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+");");
3684 gen.add("}");
3685 gen.add(ctx.getCallPath()+" = "+tnd->castToCpp(valueVariable)+";");
3689 // generate attribute
3691 Gen.addAttribute(tnd->getName(), cppName()+"["+ind->getSizeName()+"]", "attributes");
3694 // generate init
3696 if (!ClassNode->indexUsedInInit)
3698 InitId.add("uint\ti;");
3699 ClassNode->indexUsedInInit = true;
3702 InitId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\t"+cppName()+"[i] = "+tnd->getDefaultValue()+";");
3705 // generate create code
3709 // generate fetch code
3711 if (!ClassNode->indexUsedInFetch)
3713 FetchId.add("uint\ti;");
3714 ClassNode->indexUsedInFetch = true;
3717 if (tnd->isEnum())
3718 FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\tdata.serialEnum("+cppName()+"[i]);");
3719 else if (tnd->CppType != tnd->StorageType)
3721 FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)");
3722 FetchId.add("{");
3723 FetchId.add(tnd->StorageType+"\t_v;");
3724 FetchId.add("data.serial(_v);");
3725 FetchId.add(cppName()+"[i] = "+tnd->castToCpp("_v")+";");
3726 FetchId.add("}");
3728 else
3730 FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\tdata.serial("+cppName()+"[i]);");
3734 // generate clear code
3736 if (ctx.getRootCaller()->HasRowAccess)
3738 string forIndex = "__i"+toString(ctx.getContextIndex());
3739 ctx.getRootCaller()->ClearId.add("for (uint "+forIndex+"=0; "+forIndex+"<"+ind->getSizeName()+"; ++"+forIndex+")");
3740 ctx.getRootCaller()->ClearId.add("{");
3741 ctx.getRootCaller()->ClearId.add(ctx.getCallPath()+" = "+tnd->getDefaultValue()+";");
3742 ctx.getRootCaller()->ClearId.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(tnd->getDefaultValue())+");");
3743 ctx.getRootCaller()->ClearId.add("}");
3752 void CDeclarationNode::generateArrayClassContent(CCallContext *context)
3754 setEnv("decltype", "arrayclass");
3756 CClassGenerator &Gen = ClassNode->Gen;
3757 CCppOutput& DbSummary = getDbNode()->DbSummary;
3759 CClassGenerator::SMethodId &InitId = ClassNode->InitId;
3760 CClassGenerator::SMethodId &ClearId = ClassNode->ClearId;
3761 CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId;
3762 CClassGenerator::SMethodId &FetchId = ClassNode->FetchId;
3763 CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId;
3764 CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId;
3765 CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId;
3766 CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId;
3767 CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId;
3768 CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId;
3770 CClassNode *sub = getClassNode(Type);
3771 CIndexNode *ind = getIndexNode(ArrayIndex);
3772 XmlNode += " type='arrayclass' classid='"+toString(sub->Id)+"' indexid='"+toString(ind->Id)+"'";
3774 setEnv("type", Type);
3775 setEnv("indexsize", ind->getSizeName());
3777 // EGS Compat
3778 // -- begin
3780 CClassGenerator::SMethodId& StoreId = ClassNode->StoreId;
3781 CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId;
3783 generateArrayApplyCode();
3784 generateArrayStoreCode();
3786 // StoreId.add("__pdr.pushStructBegin("+tokenName()+");");
3787 StoreId.add("__pdr.pushStructBegin(__Tok_MapVal);");
3788 StoreId.add(cppName()+"[index].store(__pdr);");
3789 StoreId.add("__pdr.pushStructEnd(__Tok_MapVal);");
3790 // StoreId.add("__pdr.pushStructEnd("+tokenName()+");");
3792 ApplyId.add("if (index < "+ind->getSizeName()+")");
3793 ApplyId.add("{");
3794 // ApplyId.add("__pdr.popStructBegin("+tokenName()+");");
3795 ApplyId.add("__pdr.popStructBegin(__pdr.peekNextToken());");
3796 ApplyId.add(cppName()+"[index].apply(__pdr);");
3797 ApplyId.add("__pdr.popStructEnd(__pdr.peekNextToken());");
3798 // ApplyId.add("__pdr.popStructEnd("+tokenName()+");");
3799 ApplyId.add("}");
3800 ApplyId.add("else");
3801 ApplyId.add("{");
3802 ApplyId.add( "__pdr.skipStruct();");
3803 ApplyId.add("}");
3805 generateArrayEndCode();
3807 // -- end
3811 // export class accessors into root caller
3814 CCallContext ctx;
3815 if (context != NULL)
3816 ctx = *context;
3817 ctx.Context.push_back(this);
3819 if (ctx.getRootCaller()->HasRowAccess)
3821 string forIndex = "__i"+toString(ctx.getContextIndex());
3822 ctx.getRootCaller()->ClearId.add("for (uint "+forIndex+"=0; "+forIndex+"<"+ind->getSizeName()+"; ++"+forIndex+")");
3823 ctx.getRootCaller()->ClearId.add("{");
3826 sub->generateContentInCall(&ctx);
3828 if (ctx.getRootCaller()->HasRowAccess)
3830 ctx.getRootCaller()->ClearId.add("}");
3834 // generate attribute
3836 Gen.addAttribute(Type, cppName()+"["+ind->getSizeName()+"]", "attributes");
3839 // generate init
3843 // generate create code
3847 // generate fetch code
3849 if (!ClassNode->indexUsedInFetch)
3851 FetchId.add("uint\ti;");
3852 ClassNode->indexUsedInFetch = true;
3854 FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\t"+cppName()+"[i]."+fetchFunction+"(data);");
3857 // generate clear code
3866 void CDeclarationNode::generateArrayRefContent(CCallContext *context)
3868 setEnv("decltype", "arrayref");
3870 CClassGenerator &Gen = ClassNode->Gen;
3871 CCppOutput& DbSummary = getDbNode()->DbSummary;
3873 CClassGenerator::SMethodId &InitId = ClassNode->InitId;
3874 CClassGenerator::SMethodId &ClearId = ClassNode->ClearId;
3875 CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId;
3876 CClassGenerator::SMethodId &FetchId = ClassNode->FetchId;
3877 CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId;
3878 CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId;
3879 CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId;
3880 CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId;
3881 CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId;
3882 CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId;
3883 CClassGenerator::SMethodId &NotifyInitId = ClassNode->NotifyInitId;
3884 CClassGenerator::SMethodId &NotifyReleaseId = ClassNode->NotifyReleaseId;
3886 CClassNode *cnd = getClassNode(Type);
3888 bool useReference = cnd->ForceReference;
3890 CDeclarationNode *dnd = cnd->getDeclarationNode(ForwardRefAttribute);
3891 CIndexNode *ind = getIndexNode(ArrayIndex);
3892 CDeclarationNode *knd = cnd->getKey();
3893 XmlNode += " type='arrayref' classid='"+toString(cnd->Id)+"' forwardreferedid='"+toString(dnd->Id)+"' key='"+toString(knd->Id)+"' indexid='"+toString(ind->Id)+"' allownull='"+(useReference ? "true" : "false")+"'";
3895 string arrayType = Type+(useReference ? "*" : "");
3896 string access = (useReference ? "->" : ".");
3898 setEnv("type", Type);
3899 setEnv("indexsize", ind->getSizeName());
3900 define(useReference, "useref");
3902 string UCodeContext;
3903 if (context != NULL)
3904 UCodeContext = context->getUserCodeContext();
3906 string onChangeUser = getUserCode("onChange", UCodeContext);
3908 // EGS Compat
3909 // -- begin
3911 CClassGenerator::SMethodId& StoreId = ClassNode->StoreId;
3912 CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId;
3914 generateArrayStoreCode();
3915 generateArrayApplyCode();
3917 StoreId.add("__pdr.pushStructBegin("+tokenName()+");");
3919 ApplyId.add("if (index < "+ind->getSizeName()+")");
3920 ApplyId.add("{");
3921 ApplyId.add( "if (__pdr.peekNextToken() == "+tokenName()+")");
3922 ApplyId.add( "{");
3923 ApplyId.add( "__pdr.popStructBegin("+tokenName()+");");
3925 if (useReference)
3927 generateClassPtrStoreCode(cppName()+"[index]");
3929 generateClassPtrApplyCode(cppName()+"[index]");
3931 else
3933 StoreId.add(cppName()+"[index].store(__pdr);");
3935 ApplyId.add(cppName()+"[index].apply(__pdr);");
3936 ApplyId.add(cppName()+"[index]."+setUnnotifiedParentFunction+"(this);");
3939 StoreId.add("__pdr.pushStructEnd("+tokenName()+");");
3941 ApplyId.add( "__pdr.popStructEnd("+tokenName()+");");
3942 ApplyId.add( "}");
3943 ApplyId.add("}");
3944 ApplyId.add("else");
3945 ApplyId.add("{");
3946 ApplyId.add( "__pdr.skipStruct();");
3947 ApplyId.add("}");
3949 generateArrayEndCode();
3951 // -- end
3955 // generate read accessor
3957 Gen.startMethod((useReference ? arrayType : Type+"&"), getFunc(), ind->getName()+" "+indexVariable, "methods", false, inlineAccessors);
3958 Gen.add(ind->checkCode(indexVariable));
3959 Gen.add("return "+cppName()+"["+indexVariable+"];");
3961 Gen.startMethod(string("const ")+(useReference ? arrayType : Type+"&"), getFunc(), ind->getName()+" "+indexVariable, "methods", true, inlineAccessors);
3962 Gen.add(ind->checkCode(indexVariable));
3963 Gen.add("return "+cppName()+"["+indexVariable+"];");
3965 DbSummary << "\t" << getFunc() << "\n";
3968 // generate write accessor
3970 if (useReference)
3972 Gen.startMethod("void", setFunc(), arrayType+" "+valueVariable, "methods", false, inlineAccessors);
3974 DbSummary << "\t" << setFunc() << "\n";
3976 Gen.add("if ("+valueVariable+" == NULL)\treturn;");
3977 Gen.add(ind->getName()+"\t"+keyVariable+" = "+valueVariable+"->"+cnd->getKey()->getFunc()+"();");
3978 Gen.add(ind->checkCode(keyVariable));
3979 Gen.add(Type+"*\t__prev = "+cppName()+"["+keyVariable+"];");
3980 Gen.add("if (__prev != NULL)");
3981 Gen.add("{");
3982 Gen.add("__prev->"+setParentFunction+"(NULL);");
3983 if (cnd->MapClass == NULL)
3985 Gen.add("__prev->"+unregisterFunction+"();");
3986 Gen.add("__prev->"+destroyFunction+"();");
3987 Gen.add("delete __prev;");
3989 Gen.add("}");
3990 Gen.add(valueVariable+"->"+setParentFunction+"(this);");
3991 Gen.add(cppName()+"["+keyVariable+"] = "+valueVariable+";");
3994 if (cnd->MapClass == NULL && useReference && !cnd->HasInheritance && !cnd->DerivatedFlag)
3996 Gen.startMethod(Type+"*", newFunc(), ind->getName()+" "+indexVariable, "methods", false, inlineAccessors);
3997 DbSummary << "\t" << newFunc() << "\n";
3998 Gen.add(ind->checkCode(indexVariable));
3999 Gen.add(Type+"*\t"+objectVariable+" = new "+Type+"();");
4000 Gen.add(objectVariable+"->"+initFunction+"("+indexVariable+");");
4001 Gen.add(objectVariable+"->"+registerFunction+"();");
4002 Gen.add(setFunc()+"("+objectVariable+");");
4005 if (cnd->MapClass == NULL && useReference)
4007 Gen.startMethod("void", deleteFunc(), ind->getName()+" "+indexVariable, "methods", false, inlineAccessors);
4008 DbSummary << "\t" << deleteFunc() << "\n";
4009 Gen.add(ind->checkCode(indexVariable));
4010 Gen.add(Type+"*\t"+objectVariable+" = "+cppName()+"["+indexVariable+"];");
4011 Gen.add(objectVariable+"->"+setParentFunction+"(NULL);");
4012 Gen.add(objectVariable+"->"+unregisterFunction+"();");
4013 Gen.add(objectVariable+"->"+destroyFunction+"();");
4014 Gen.add("delete "+objectVariable+";");
4018 // generate attribute
4020 Gen.addAttribute(arrayType, cppName()+"["+ind->getSizeName()+"]", "attributes");
4023 // generate init
4025 if (!ClassNode->indexUsedInInit)
4027 InitId.add("uint\ti;");
4028 ClassNode->indexUsedInInit = true;
4030 if (useReference)
4032 InitId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\t"+cppName()+"[i] = NULL;");
4034 else
4036 InitId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\t"+cppName()+"[i]."+initFunction+"(("+ind->getName()+")i);");
4040 // generate destroy code
4042 if (!ClassNode->indexUsedInDestroy)
4044 DestroyId.add("uint\ti;");
4045 ClassNode->indexUsedInDestroy = true;
4047 DestroyId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)");
4048 DestroyId.add("{");
4049 if (useReference)
4051 DestroyId.add("if ("+cppName()+"[i] != NULL)");
4052 DestroyId.add("{");
4053 DestroyId.add(Type+"*\t"+objectVariable+" = "+cppName()+"[i];");
4054 DestroyId.add(objectVariable+"->"+destroyFunction+"();");
4055 DestroyId.add("delete "+objectVariable+";");
4056 DestroyId.add("}");
4058 else
4060 DestroyId.add(cppName()+"[i]."+destroyFunction+"();");
4062 DestroyId.add("}");
4065 // generate create code
4069 // generate fetch code
4071 if (useReference)
4073 if (!ClassNode->indexUsedInFetch)
4075 FetchId.add("uint\ti;");
4076 ClassNode->indexUsedInFetch = true;
4078 if (!ClassNode->tableAndRowIndicesUsedInFetch)
4080 FetchId.add(TTableIndexName+"\ttableIndex;\n"+TRowIndexName+"\trowIndex;");
4081 ClassNode->tableAndRowIndicesUsedInFetch = true;
4083 FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)");
4084 FetchId.add("{");
4085 FetchId.add(cppName()+"[i] = NULL;");
4086 FetchId.add("// read table and row, create an object, affect to the ref, and fetch it");
4087 FetchId.add("data.serial(tableIndex, rowIndex);");
4088 FetchId.add("if (rowIndex != "+INVALID_ROW_INDEXName+" && tableIndex != "+INVALID_TABLE_INDEXName+")");
4089 FetchId.add("{");
4090 FetchId.add(cppName()+"[i] = static_cast<"+Type+"*>("+pdslibFunc("create")+"(tableIndex));");
4091 FetchId.add(pdslibFunc("setRowIndex")+"(rowIndex, "+cppName()+"[i]);");
4092 FetchId.add(cppName()+"[i]->"+fetchFunction+"(data);");
4093 FetchId.add(cppName()+"[i]->"+setUnnotifiedParentFunction+"(this);");
4094 FetchId.add("}");
4095 FetchId.add("}");
4097 else
4099 if (!ClassNode->indexUsedInFetch)
4101 FetchId.add("uint\ti;");
4102 ClassNode->indexUsedInFetch = true;
4104 if (!ClassNode->tableAndRowIndicesUsedInFetch)
4106 FetchId.add(TTableIndexName+"\ttableIndex;\n"+TRowIndexName+"\trowIndex;");
4107 ClassNode->tableAndRowIndicesUsedInFetch = true;
4109 FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)");
4110 FetchId.add("{");
4111 FetchId.add("// read table and row, create an object, affect to the ref, and fetch it");
4112 FetchId.add("data.serial(tableIndex, rowIndex);");
4113 FetchId.add("if (rowIndex != "+INVALID_ROW_INDEXName+" && tableIndex != "+INVALID_TABLE_INDEXName+")");
4114 FetchId.add("{");
4115 FetchId.add(pdslibFunc("setRowIndex")+"(rowIndex, &"+cppName()+"[i]);");
4116 FetchId.add(cppName()+"[i]."+fetchFunction+"(data);");
4117 FetchId.add(cppName()+"[i]."+setUnnotifiedParentFunction+"(this);");
4118 FetchId.add("}");
4119 FetchId.add("}");
4123 // generate register/unregister code
4125 if (!useReference)
4127 if (!ClassNode->indexUsedInRegister)
4129 RegisterAttributesId.add("uint\ti;");
4130 ClassNode->indexUsedInRegister = true;
4132 RegisterAttributesId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)");
4133 RegisterAttributesId.add("{");
4134 RegisterAttributesId.add(cppName()+"[i]."+registerFunction+"();");
4135 RegisterAttributesId.add(cppName()+"[i]."+setParentFunction+"(this);");
4136 RegisterAttributesId.add("}");
4138 if (!ClassNode->indexUsedInUnregister)
4140 UnregisterAttributesId.add("uint\ti;");
4141 ClassNode->indexUsedInUnregister = true;
4143 UnregisterAttributesId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)");
4144 UnregisterAttributesId.add("{");
4145 UnregisterAttributesId.add(cppName()+"[i]."+unregisterFunction+"();");
4146 UnregisterAttributesId.add("}");
4148 else
4150 if (!ClassNode->indexUsedInUnregister)
4152 UnregisterAttributesId.add("uint\ti;");
4153 ClassNode->indexUsedInUnregister = true;
4155 UnregisterAttributesId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)");
4156 UnregisterAttributesId.add("{");
4157 UnregisterAttributesId.add("if ("+cppName()+"[i] != NULL)");
4158 UnregisterAttributesId.add("{");
4159 UnregisterAttributesId.add(Type+"*\t"+objectVariable+" = "+cppName()+"[i];");
4160 UnregisterAttributesId.add(objectVariable+"->"+unregisterFunction+"();");
4161 UnregisterAttributesId.add(objectVariable+"->"+destroyFunction+"();");
4162 UnregisterAttributesId.add("delete "+objectVariable+";");
4163 UnregisterAttributesId.add("}");
4164 UnregisterAttributesId.add("}");
4168 // generate init/release notification
4171 if (!ClassNode->indexUsedInNotifyInit)
4173 NotifyInitId.add("uint\ti;");
4174 ClassNode->indexUsedInNotifyInit = true;
4176 NotifyInitId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)");
4177 NotifyInitId.add("{");
4179 if (!ClassNode->indexUsedInNotifyRelease)
4181 NotifyReleaseId.add("uint\ti;");
4182 ClassNode->indexUsedInNotifyRelease = true;
4184 NotifyReleaseId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)");
4185 NotifyReleaseId.add("{");
4187 if (!useReference)
4189 NotifyInitId.add(cppName()+"[i]."+notifyInitFunction+"();");
4191 NotifyReleaseId.add(cppName()+"[i]."+notifyReleaseFunction+"();");
4193 else
4195 NotifyInitId.add("if ("+cppName()+"[i] != NULL)");
4196 NotifyInitId.add("{");
4197 NotifyInitId.add(cppName()+"[i]->"+notifyInitFunction+"();");
4198 NotifyInitId.add("}");
4200 NotifyReleaseId.add("if ("+cppName()+"[i] != NULL)");
4201 NotifyReleaseId.add("{");
4202 NotifyReleaseId.add(cppName()+"[i]->"+notifyReleaseFunction+"();");
4203 NotifyReleaseId.add("}");
4206 NotifyInitId.add("}");
4207 NotifyReleaseId.add("}");
4211 // generate unlink code
4213 if (useReference)
4215 Gen.startMethod("void", unlinkFunc(), ind->getName()+" "+keyVariable, "internal", false, inlineInternal);
4216 Gen.add(cppName()+"["+keyVariable+"] = NULL;");
4220 // generate clear code
4222 ClearId.add("for (uint i=0; i<"+ind->getSizeName()+"; ++i)");
4223 ClearId.add("{");
4224 if (!useReference)
4226 ClearId.add(cppName()+"[i]."+clearFunction+"();");
4228 else
4230 //ClearId.add(cppName()+"[i]->"+setParentFunction+"(NULL);");
4231 ClearId.add(Type+"*\t"+objectVariable+" = "+cppName()+"[i];");
4232 ClearId.add(objectVariable+"->"+unregisterFunction+"();");
4233 ClearId.add(objectVariable+"->"+destroyFunction+"();");
4234 ClearId.add("delete "+objectVariable+";");
4236 ClearId.add("}");
4245 void CDeclarationNode::generateSetContent(CCallContext *context)
4247 setEnv("decltype", "set");
4249 CClassGenerator &Gen = ClassNode->Gen;
4250 CCppOutput& DbSummary = getDbNode()->DbSummary;
4252 CClassGenerator::SMethodId &InitId = ClassNode->InitId;
4253 CClassGenerator::SMethodId &ClearId = ClassNode->ClearId;
4254 CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId;
4255 CClassGenerator::SMethodId &FetchId = ClassNode->FetchId;
4256 CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId;
4257 CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId;
4258 CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId;
4259 CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId;
4260 CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId;
4261 CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId;
4262 CClassGenerator::SMethodId &NotifyInitId = ClassNode->NotifyInitId;
4263 CClassGenerator::SMethodId &NotifyReleaseId = ClassNode->NotifyReleaseId;
4265 CClassNode *sub = getClassNode(Type);
4266 CDeclarationNode *key = sub->getKey();
4267 CTypeNode *keyType = getTypeNode(key->Type);
4269 bool useReference = sub->ForceReference;
4270 string access = (useReference ? "->" : ".");
4272 string onChangeUser = getUserCode("onChange", context != NULL ? context->getUserCodeContext() : "");
4275 string setType = "std::map<"+keyType->getName()+", " + Type + (useReference ? "*" : "") + ">";
4277 CDeclarationNode *dnd = sub->getDeclarationNode(ForwardRefAttribute);
4278 XmlNode += " type='set' classid='"+toString(sub->Id)+"' forwardreferedid='"+toString(dnd->Id)+"' key='"+toString(key->Id)+"' ";
4280 setEnv("type", Type);
4281 setEnv("keytype", keyType->getName());
4282 define(useReference, "useref");
4284 // EGS Compat
4285 // -- begin
4287 CClassGenerator::SMethodId& StoreId = ClassNode->StoreId;
4288 CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId;
4290 StoreId.add("// store "+Name);
4291 StoreId.add("__pdr.pushStructBegin("+tokenName()+");");
4292 StoreId.add("for ("+setType+"::const_iterator it="+cppName()+".begin(); it!="+cppName()+".end(); ++it)");
4293 StoreId.add("{");
4294 StoreId.add( keyType->getName()+"\tkey = (*it).first;");
4295 keyType->generateStoreCode(StoreId, "__Tok_MapKey", "key");
4296 StoreId.add( "__pdr.pushStructBegin(__Tok_MapVal);");
4298 if (useReference)
4300 generateClassPtrStoreCode("(*it).second");
4302 else
4304 StoreId.add("(*it).second.store(__pdr);");
4307 StoreId.add( "__pdr.pushStructEnd(__Tok_MapVal);");
4308 StoreId.add("}");
4309 StoreId.add("__pdr.pushStructEnd("+tokenName()+");");
4310 StoreId.add("// end of store "+Name);
4312 ApplyId.add("// apply "+Name);
4313 ApplyId.add("else if (__pdr.peekNextToken() == "+tokenName()+")");
4314 ApplyId.add("{");
4315 ApplyId.add( "__pdr.popStructBegin("+tokenName()+");");
4316 ApplyId.add( "while (!__pdr.isEndOfStruct())");
4317 ApplyId.add( "{");
4318 ApplyId.add( keyType->getName()+"\tkey;");
4319 keyType->generateApplyCode(ApplyId, "__Tok_MapKey", "key");
4321 ApplyId.add( "__pdr.popStructBegin(__Tok_MapVal);");
4322 if (useReference)
4324 ApplyId.add( Type+"*\tobj;");
4325 generateClassPtrApplyCode("obj");
4326 ApplyId.add( "if (obj != NULL)");
4327 ApplyId.add( "{");
4328 ApplyId.add( cppName()+"[key] = obj;");
4329 ApplyId.add( "}");
4331 else
4333 ApplyId.add( Type+"&\tobj = "+cppName()+"[key];");
4334 ApplyId.add( "obj.apply(__pdr);");
4335 ApplyId.add( "obj."+setUnnotifiedParentFunction+"(this);");
4337 ApplyId.add( "__pdr.popStructEnd(__Tok_MapVal);");
4338 ApplyId.add( "}");
4339 ApplyId.add( "__pdr.popStructEnd("+tokenName()+");");
4340 ApplyId.add("}");
4341 ApplyId.add("// end of apply "+Name);
4343 // -- end
4347 // generate read accessor
4349 Gen.startMethod(Type+"*", getFunc(), "const "+keyType->getName()+"& "+keyVariable, "methods", false, inlineAccessors);
4350 DbSummary << "\t" << getFunc() << "\n";
4351 Gen.add(setType+"::iterator _it = "+cppName()+".find("+keyVariable+");");
4352 Gen.add("return (_it=="+cppName()+".end() ? NULL : "+(useReference ? "(*_it).second" : "&((*_it).second)")+");");
4354 Gen.startMethod("const "+Type+"*", getFunc(), "const "+keyType->getName()+"& "+keyVariable, "methods", true, inlineAccessors);
4355 Gen.add(setType+"::const_iterator _it = "+cppName()+".find("+keyVariable+");");
4356 Gen.add("return (_it=="+cppName()+".end() ? NULL : "+(useReference ? "(*_it).second" : "&((*_it).second)")+");");
4358 // generate map accessor
4359 string stypedef = "T"+Name+"Map";
4360 //Gen.addOther("typedef "+setType+"\t"+stypedef+";");
4361 Gen.startMethod(setType+"::iterator", getFunc()+"Begin", "", "methods", false, inlineAccessors);
4362 Gen.add("return "+cppName()+".begin();");
4363 DbSummary << "\t" << getFunc() << "Begin" << "\n";
4364 Gen.startMethod(setType+"::iterator", getFunc()+"End", "", "methods", false, inlineAccessors);
4365 Gen.add("return "+cppName()+".end();");
4366 DbSummary << "\t" << getFunc() << "End" << "\n";
4367 Gen.startMethod(setType+"::const_iterator", getFunc()+"Begin", "", "methods", true, inlineAccessors);
4368 Gen.add("return "+cppName()+".begin();");
4369 Gen.startMethod(setType+"::const_iterator", getFunc()+"End", "", "methods", true, inlineAccessors);
4370 Gen.add("return "+cppName()+".end();");
4371 Gen.startMethod("const "+setType+" &", getFunc(), "", "methods", true, inlineAccessors);
4372 Gen.add("return "+cppName()+";");
4375 // generate write accessor
4377 if (useReference)
4379 Gen.startMethod("void", setFunc(), Type+"* "+valueVariable, "methods", false, inlineAccessors);
4380 DbSummary << "\t" << setFunc() << "\n";
4381 Gen.add("if ("+valueVariable+" == NULL)\treturn;");
4382 Gen.add(keyType->getName()+"\t"+keyVariable+" = "+valueVariable+"->"+sub->getKey()->getFunc()+"();");
4383 Gen.add(setType+"::iterator\t_it = "+cppName()+".find("+keyVariable+");");
4384 Gen.add("if (_it != "+cppName()+".end())");
4385 Gen.add("{");
4386 Gen.add(Type+"*\t__prev = (*_it).second;");
4387 Gen.add("if (__prev == "+valueVariable+")\treturn;");
4388 Gen.add("__prev->"+setParentFunction+"(NULL);");
4389 Gen.add("__prev->"+unregisterFunction+"();");
4390 Gen.add("__prev->"+destroyFunction+"();");
4391 Gen.add("delete __prev;");
4392 Gen.add("}");
4393 Gen.add(valueVariable+"->"+setParentFunction+"(this);");
4394 Gen.add(cppName()+"["+keyVariable+"] = "+valueVariable+";");
4395 if (!onChangeUser.empty())
4397 Gen.add("{");
4398 Gen.add(onChangeUser);
4399 Gen.add("}");
4403 if (sub->MapClass == NULL && !sub->HasInheritance && !sub->DerivatedFlag)
4405 Gen.startMethod(Type+"*", newFunc(), "const "+keyType->getName()+" &"+keyVariable, "methods", false, inlineAccessors);
4406 DbSummary << "\t" << newFunc() << "\n";
4407 Gen.add(setType+"::iterator\t__it = "+cppName()+".find("+keyVariable+");");
4408 Gen.add("if (__it == "+cppName()+".end())");
4409 Gen.add("{");
4410 Gen.add("__it = "+cppName()+".insert("+setType+"::value_type("+keyVariable+", "+(useReference ? toString("new ") : toString(""))+Type+"())).first;");
4411 Gen.add(Type+"*\t"+objectVariable+" = "+(useReference ? toString("") : toString("&"))+"((*__it).second);");
4412 Gen.add(objectVariable+"->"+initFunction+"("+keyVariable+");");
4413 Gen.add(objectVariable+"->"+registerFunction+"();");
4414 Gen.add(objectVariable+"->"+setParentFunction+"(this);");
4415 Gen.add("}");
4416 if (!onChangeUser.empty())
4418 Gen.add("{");
4419 Gen.add(onChangeUser);
4420 Gen.add("}");
4422 Gen.add("return "+(useReference ? toString("") : toString("&"))+"((*__it).second);");
4425 Gen.startMethod("void", deleteFunc(), "const "+keyType->getName()+" &"+keyVariable, "methods", false, inlineAccessors);
4426 DbSummary << "\t" << deleteFunc() << "\n";
4427 Gen.add(setType+"::iterator\t__it = "+cppName()+".find("+keyVariable+");");
4428 Gen.add("if (__it == "+cppName()+".end())\treturn;");
4429 if (useReference)
4431 Gen.add(Type+"*\t"+objectVariable+" = (*__it).second;");
4432 Gen.add(objectVariable+"->"+unregisterFunction+"();");
4433 Gen.add(objectVariable+"->"+destroyFunction+"();");
4434 Gen.add("delete "+objectVariable+";");
4436 else
4438 Gen.add(Type+"&\t"+objectVariable+" = (*__it).second;");
4439 Gen.add(objectVariable+"."+unregisterFunction+"();");
4440 Gen.add(cppName()+".erase(__it);");
4442 if (!onChangeUser.empty())
4444 Gen.add("{");
4445 Gen.add(onChangeUser);
4446 Gen.add("}");
4450 // generate attribute
4452 Gen.addAttribute(setType, cppName(), "attributes");
4455 // generate init
4459 // generate destroy code
4461 DestroyId.add("for ("+setType+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )");
4462 DestroyId.add("{");
4463 DestroyId.add(setType+"::iterator __itr=__it++;");
4464 if (useReference)
4466 DestroyId.add(Type+"*\t"+objectVariable+" = ((*__itr).second);");
4467 DestroyId.add("if ("+objectVariable+" != NULL)");
4468 DestroyId.add("{");
4469 DestroyId.add(objectVariable+"->"+destroyFunction+"();");
4470 DestroyId.add("delete "+objectVariable+";");
4471 DestroyId.add("}");
4473 else
4475 DestroyId.add("((*__itr).second)."+destroyFunction+"();");
4477 DestroyId.add("}");
4478 DestroyId.add(cppName()+".clear();");
4481 // generate create code
4485 // generate fetch code
4487 if (!ClassNode->tableAndRowIndicesUsedInFetch)
4489 FetchId.add(TTableIndexName+"\ttableIndex;\n"+TRowIndexName+"\trowIndex;");
4490 ClassNode->tableAndRowIndicesUsedInFetch = true;
4492 FetchId.add("do");
4493 FetchId.add("{");
4494 FetchId.add("// read table and row, create an object, affect to the ref, and fetch it");
4495 FetchId.add("data.serial(tableIndex, rowIndex);");
4496 FetchId.add("if (rowIndex == "+INVALID_ROW_INDEXName+" || tableIndex == "+INVALID_TABLE_INDEXName+")\tbreak;");
4498 FetchId.add(keyType->getName()+"\t"+keyVariable+";");
4499 if (keyType->isEnum())
4501 FetchId.add("data.serialEnum("+keyVariable+");");
4503 else if (keyType->CppType != keyType->StorageType)
4505 FetchId.add("{");
4506 FetchId.add(keyType->StorageType+"\t_v;");
4507 FetchId.add("data.serial(_v);");
4508 FetchId.add(keyVariable+" = "+keyType->castToCpp("_v")+";");
4509 FetchId.add("}");
4511 else
4513 FetchId.add("data.serial("+keyVariable+");");
4515 if (useReference)
4517 FetchId.add(Type+"*\t"+objectVariable+" = static_cast<"+Type+"*>("+pdslibFunc("create")+"(tableIndex));");
4518 FetchId.add(cppName()+".insert(std::make_pair("+keyVariable+", "+objectVariable+"));");
4520 else
4522 FetchId.add(cppName()+".insert(std::make_pair("+keyVariable+", "+Type+"()));");
4523 FetchId.add(Type+"*\t"+objectVariable+" = &("+cppName()+"["+keyVariable+"]);");
4525 FetchId.add(pdslibFunc("setRowIndex")+"(rowIndex, "+objectVariable+");");
4526 FetchId.add(objectVariable+"->"+fetchFunction+"(data);");
4527 FetchId.add(objectVariable+"->"+setUnnotifiedParentFunction+"(this);");
4528 FetchId.add("}");
4529 FetchId.add("while (true);");
4532 // generate register/unregister code
4535 UnregisterAttributesId.add("for ("+setType+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )");
4536 UnregisterAttributesId.add("{");
4537 UnregisterAttributesId.add(setType+"::iterator __itr=__it++;");
4538 if (useReference)
4540 UnregisterAttributesId.add(Type+"*\t"+objectVariable+" = (*__itr).second;");
4541 UnregisterAttributesId.add(objectVariable+"->"+unregisterFunction+"();");
4542 UnregisterAttributesId.add(objectVariable+"->"+destroyFunction+"();");
4543 UnregisterAttributesId.add("delete "+objectVariable+";");
4545 else
4547 UnregisterAttributesId.add(Type+"&\t"+objectVariable+" = (*__itr).second;");
4548 UnregisterAttributesId.add(objectVariable+"."+unregisterFunction+"();");
4550 UnregisterAttributesId.add("}");
4553 // generate init/release notification
4556 NotifyInitId.add("for ("+setType+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )");
4557 NotifyInitId.add("{");
4558 NotifyInitId.add(setType+"::iterator __itr=__it++;");
4560 NotifyReleaseId.add("for ("+setType+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )");
4561 NotifyReleaseId.add("{");
4562 NotifyReleaseId.add(setType+"::iterator __itr=__it++;");
4564 if (!useReference)
4566 NotifyInitId.add("(*__itr).second."+notifyInitFunction+"();");
4567 NotifyReleaseId.add("(*__itr).second."+notifyReleaseFunction+"();");
4569 else
4571 NotifyInitId.add("(*__itr).second->"+notifyInitFunction+"();");
4572 NotifyReleaseId.add("(*__itr).second->"+notifyReleaseFunction+"();");
4575 NotifyInitId.add("}");
4576 NotifyReleaseId.add("}");
4579 // generate unlink code
4581 if (useReference)
4583 Gen.startMethod("void", unlinkFunc(), keyType->getName()+" "+keyVariable, "internal", false, inlineInternal);
4584 Gen.add(cppName()+".erase("+keyVariable+");");
4588 // generate clear code
4590 ClearId.add("for ("+setType+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )");
4591 ClearId.add("{");
4592 ClearId.add(setType+"::iterator __itr=__it++;");
4593 if (!useReference)
4595 ClearId.add(Type+"*\t"+objectVariable+" = &((*__itr).second);");
4597 else
4599 ClearId.add(Type+"*\t"+objectVariable+" = (*__itr).second;");
4601 //ClearId.add(objectVariable+"->"+setParentFunction+"(NULL);");
4602 ClearId.add(objectVariable+"->"+unregisterFunction+"();");
4603 ClearId.add(objectVariable+"->"+destroyFunction+"();");
4604 if (useReference)
4606 ClearId.add("delete "+objectVariable+";");
4608 ClearId.add("}");
4609 ClearId.add(cppName()+".clear();");
4613 string CDeclarationNode::displayPrintfPrefix()
4615 if (DeclarationType != SimpleType)
4616 error("can't display other declaration than simple type", "internal");
4618 CTypeNode* type = getTypeNode(Type);
4620 if (type->CppType == "CEntityId" || type->CppType == "CSheetId")
4621 return "%s";
4622 else if (type->CppType == "uint64" || type->CppType == "sint64")
4623 return "%\"NL_I64\"d";
4624 else if (type->CppType == "float" || type->CppType == "double")
4625 return "%g";
4626 else
4627 return "%d";
4630 string CDeclarationNode::displayCppCode(string replVar)
4632 if (DeclarationType != SimpleType)
4633 error("can't display other declaration than simple type", "internal");
4635 if (replVar.empty())
4636 replVar = cppName();
4638 CTypeNode* type = getTypeNode(Type);
4640 if (type->CppType == "CEntityId" || type->CppType == "CSheetId")
4641 return replVar+".toString().c_str()";
4642 else
4643 return replVar;
4647 string CDeclarationNode::toUint64(string replVar)
4649 if (DeclarationType != SimpleType)
4650 error("can't display other declaration than simple type", "internal");
4652 if (replVar.empty())
4653 replVar = cppName();
4655 CTypeNode* type = getTypeNode(Type);
4657 if (type->CppType == "CEntityId")
4658 return replVar+".asUint64()";
4659 else if (type->CppType == "CSheetId")
4660 return "(uint64)("+replVar+".asInt())";
4661 else
4662 return "(uint64)"+replVar;
4669 bool CLogMsgNode::prolog()
4671 getDbNode()->LogNodes.push_back(this);
4673 getFileNode()->IncludeDbFile = true;
4674 getFileNode()->IncludeStandard = true;
4675 getFileNode()->IncludePDSLib = true;
4677 return true;
4680 void CLogMsgNode::generateContent()
4683 uint j;
4685 CFunctionGenerator logfunc;
4686 CClassGenerator logclass;
4687 string argcall;
4689 CFunctionGenerator& initDb = getDbNode()->initDb;
4691 logfunc.init(Name);
4692 logfunc.setType("void");
4693 logfunc.IsInline = inlineLogFunctions;
4695 logclass.init("Log"+Name);
4696 logclass.createPublic("pub");
4697 logclass.createPrivate("priv");
4699 CClassGenerator::SMethodId startlogid = logclass.startMethod("void", logStartFunction, "", "priv", false, inlineLogFunctions);
4700 CClassGenerator::SMethodId stoplogid = logclass.startMethod("void", logStopFunction, "", "priv", false, inlineLogFunctions);
4701 startlogid.add(pdslibFunc("pushContext")+"();");
4702 stoplogid.add(pdslibFunc("popContext")+"();");
4704 map<string, CParseNode*> params;
4706 for (j=0; j<Params.size(); ++j)
4708 string type = Params[j].first;
4709 string name = Params[j].second;
4711 CTypeNode *tnd;
4712 CClassNode *cnd;
4713 if ( (tnd = getTypeNode(type, false)) )
4715 pair<map<string, CParseNode*>::iterator, bool> res = params.insert(std::pair<string, CParseNode*>(name, tnd));
4716 if (!res.second)
4717 error("log parameter '"+name+"' already defined");
4719 if (!logfunc.Proto.empty())
4720 logfunc.Proto += ", ";
4721 if (!argcall.empty())
4722 argcall += ", ";
4724 logfunc.Proto += tnd->getName()+" "+name;
4725 argcall += name;
4727 else if ( (cnd = getClassNode(type, false)) )
4729 pair<map<string, CParseNode*>::iterator, bool> res = params.insert(std::pair<string, CParseNode*>(name, cnd));
4730 if (!res.second)
4731 error("log parameter '"+name+"' already defined");
4733 if (!logfunc.Proto.empty())
4734 logfunc.Proto += ", ";
4735 if (!argcall.empty())
4736 argcall += ", ";
4738 logfunc.Proto += "const "+type+"& "+name;
4739 argcall += name;
4741 else if (type == "string")
4743 CExtLogTypeNode* extnd = new CExtLogTypeNode();
4744 extnd->ExtLogType = "string";
4745 pair<map<string, CParseNode*>::iterator, bool> res = params.insert(std::pair<string, CParseNode*>(name, extnd));
4746 if (!res.second)
4747 error("log parameter '"+name+"' already defined");
4749 if (!logfunc.Proto.empty())
4750 logfunc.Proto += ", ";
4751 if (!argcall.empty())
4752 argcall += ", ";
4754 logfunc.Proto += "const std::string& "+name;
4755 argcall += name;
4757 else
4759 error("'"+type+"' not found as a class or a type");
4764 initDb.add("// Init "+Name+" log message and parameters");
4766 for (j=0; j<Logs.size(); ++j)
4768 uint logId = Id+j;
4770 logfunc.add(pdslibFunc("log")+"("+toString(logId)+");");
4771 startlogid.add(pdslibFunc("log")+"("+toString(logId)+");");
4773 const char *cptr = Logs[j].c_str();
4774 string log;
4776 // parse log line
4778 getDbNode()->xmlDescription.push_back("<logmsg id='"+toString(logId)+"' context='"+string(Context ? "true" : "false")+"'>");
4780 uint paramNum = 0;
4782 initDb.add(pdslibFunc("initLog")+"("+toString(logId)+");");
4784 while (*cptr != '\0')
4786 if (*cptr == '$')
4788 ++cptr;
4789 if (*cptr == '\0')
4790 error("log format corrupted in line \""+Logs[j]+"\"");
4792 if (*cptr == '$')
4794 log += "$$";
4795 ++cptr;
4796 continue;
4799 string param;
4800 string var;
4802 while (*cptr!='\0' && *cptr!='$' && *cptr!='.')
4803 param += *(cptr++);
4805 if (*cptr == '\0')
4806 error("log format corrupted in line \""+Logs[j]+"\"");
4808 if (*cptr == '.')
4810 ++cptr;
4811 while (*cptr!='\0' && *cptr!='$')
4812 var += *(cptr++);
4815 if (*cptr != '$')
4816 error("log format corrupted in line \""+Logs[j]+"\"");
4818 ++cptr;
4820 map<string, CParseNode*>::iterator it = params.find(param);
4822 if (it == params.end())
4823 error("'"+param+"' ot found in prototype, at line \""+Logs[j]+"\"");
4825 CTypeNode *tnd = NULL;
4826 CExtLogTypeNode* extnd = NULL;
4828 if (var.empty())
4830 // is simple type
4831 tnd = dynamic_cast<CTypeNode*>((*it).second);
4832 extnd = dynamic_cast<CExtLogTypeNode*>((*it).second);
4833 if (tnd != NULL)
4835 logfunc.add(pdslibFunc("logPush")+"("+tnd->castToPDS(param)+");");
4836 startlogid.add(pdslibFunc("logPush")+"("+tnd->castToPDS(param)+");");
4838 else if (extnd != NULL && extnd->ExtLogType == "string")
4840 logfunc.add(pdslibFunc("logPush")+"("+param+");");
4841 startlogid.add(pdslibFunc("logPush")+"("+param+");");
4843 else
4845 error("misuse of parameter '"+param+"' at line \""+Logs[j]+"\", missing attribute name");
4848 else
4850 // is class
4851 CClassNode *cnd = dynamic_cast<CClassNode*>((*it).second);
4852 if (!cnd)
4853 error("misuse of parameter '"+param+"' at line \""+Logs[j]+"\", should be a class");
4855 CDeclarationNode *dnd = cnd->getDeclaration(var);
4857 if (!dnd->IsType)
4858 error("attribute '"+var+"' is not a simple type");
4860 tnd = getTypeNode(dnd->Type);
4862 logfunc.add(pdslibFunc("logPush")+"("+tnd->castToPDS(param+"."+dnd->getFunc()+"()")+");");
4863 startlogid.add(pdslibFunc("logPush")+"("+tnd->castToPDS(param+"."+dnd->getFunc()+"()")+");");
4866 if (tnd != NULL)
4868 getDbNode()->xmlDescription.push_back("<param id='"+toString(paramNum)+"' typeid='"+toString(tnd->Id)+"'/>");
4869 initDb.add(pdslibFunc("initLogParam")+"("+toString(logId)+", "+toString(paramNum)+", "+toString(tnd->Size)+");");
4871 else
4873 getDbNode()->xmlDescription.push_back("<param id='"+toString(paramNum)+"' typeid='"+extnd->ExtLogType+"'/>");
4874 initDb.add(pdslibFunc("initLogParam")+"("+toString(logId)+", "+toString(paramNum)+", "+toString(sizeof(uint16))+");");
4878 log += "$"+toString(paramNum);
4880 ++paramNum;
4882 else
4884 log += *(cptr++);
4888 getDbNode()->xmlDescription.push_back("<msg>"+xmlSpecialChars(log)+"</msg>");
4889 getDbNode()->xmlDescription.push_back("</logmsg>");
4892 logclass.get(startlogid).Proto = logfunc.Proto;
4894 CClassGenerator::SMethodId construct = logclass.startConstructor(logfunc.Proto, "pub", inlineLogFunctions, "");
4895 construct.add(logStartFunction+"("+argcall+");");
4896 CClassGenerator::SMethodId destruct = logclass.startDestructor("pub", inlineLogFunctions);
4897 destruct.add(logStopFunction+"();");
4899 CFileNode* file = getFileNode();
4901 if (Context)
4903 logclass.flush(file->hOutput(), file->cppOutput(), file->inlineOutput());
4904 file->hOutput() << "\n";
4906 else
4908 logfunc.flush(file->hOutput(), file->cppOutput(), file->inlineOutput());
4909 file->hOutput() << "\n";