diff --git a/utils/code_model_generator/main.cpp b/utils/code_model_generator/main.cpp index 6d765d61..52459a55 100755 --- a/utils/code_model_generator/main.cpp +++ b/utils/code_model_generator/main.cpp @@ -26,17 +26,28 @@ using namespace PICoutManipulators; void usage() { piCout << Bold << "PIP Code model generator"; piCout << Cyan << "Version" << Bold << PIPVersion() << NewLine; - piCout << Green << Bold << "Usage:" << Default << "\"pip_cmg [-hqPpEs] -o [-I] [-I] [...] [-D] [-D] [...] [] [] [...]\"" << NewLine; + piCout << Green << Bold << "Usage:" << Default << "\"pip_cmg [-hqPpsAMEST] -o [-I] [-I] [...] [-D] [-D] [...] [] [] [...]\"" << NewLine; piCout << Green << Bold << "Details:"; + piCout << Bold << "Debug control"; piCout << "-h " << Green << "- display this message and exit"; piCout << "-q " << Green << "- quiet, no debug output to console"; piCout << "-P " << Green << "- print list of all parsed files to console before exit"; piCout << "-p " << Green << "- print list of all parsed files without file with \"main\" function to console before exit"; - piCout << "-E " << Green << "- write only enums"; + piCout << ""; + piCout << Bold << "Parsing control"; piCout << "-s " << Green << "- single file (don`t follow includes)"; - piCout << "-o " << Green << "- output file for code model without extension (e.g. \"ccm\" - files \"ccm.h\" and \"ccm.cpp\" will be created)"; piCout << "-I " << Green << "- add include dir (e.g. -I.. -I../some_dir -I/usr/include)"; piCout << "-D " << Green << "- add define to preprocessor, define PICODE is always defined (e.g. -DMY_DEFINE will add MY_DEFINE define)"; + piCout << ""; + piCout << Bold << "Output control"; + piCout << "-A " << Green << "- write all"; + piCout << "-M " << Green << "- write metainfo"; + piCout << "-E " << Green << "- write enums"; + piCout << "-S " << Green << "- write stream operators"; + piCout << "-T " << Green << "- write text serialize functions"; + piCout << "-o " << Green << "- output file for code model without extension (e.g. \"ccm\" - files \"ccm.h\" and \"ccm.cpp\" will be created)"; + piCout << ""; + piCout << Bold << "Input control"; piCout << " " << Green << "- add file to code model, all includes of this file will be proceed (e.g. \"main.cpp\")"; } @@ -111,7 +122,38 @@ void makeEnumInfo(PIFile & f, const PICodeParser::Enum * e) { } -void writeModel(PICodeParser & parser, const PIString out, bool only_enums) { +void makeClassStream(PIFile & f, const PICodeParser::Entity * e) { + PIStringList ml; + piForeachC (PICodeParser::Member & m, e->members) { + if (m.is_type_ptr) continue; + ml << m.name; + } + if (ml.isEmpty()) return; + f << "\nPIByteArray & operator <<(PIByteArray & s, const " << e->name << " & v) {\n"; + f << "\ts"; + piForeachC (PIString & m, ml) + f << " << " << m << "\n\t"; + f << ";\n}\nPIByteArray & operator >>(PIByteArray & s, " << e->name << " & v) {\n"; + f << "\ts"; + piForeachC (PIString & m, ml) + f << " >> " << m << "\n\t"; + f << ";\n}\n"; +} + + +void makeClassStreamHeader(PIFile & f, const PICodeParser::Entity * e) { + PIStringList ml; + piForeachC (PICodeParser::Member & m, e->members) { + if (m.is_type_ptr) continue; + ml << m.name; + } + if (ml.isEmpty()) return; + f << "\nPIByteArray & operator <<(PIByteArray & s, const " << e->name << " & v);"; + f << "\nPIByteArray & operator >>(PIByteArray & s, " << e->name << " & v);\n"; +} + + +void writeModel(PICodeParser & parser, const PIString out, bool meta, bool enums, bool streams, bool texts) { PIVector ventities; PIString defname = out.replaceAll(".", "_").replaceAll("/", "_").replaceAll(":", "_").replaceAll("-", "_").toUpperCase() + "_H"; @@ -125,13 +167,15 @@ void writeModel(PICodeParser & parser, const PIString out, bool only_enums) { f.open(PIIODevice::WriteOnly); f << "// Generated by \"PIP Code model generator\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n\n"); f << "#include \n#include \"" << out << ".h\"\n\nusing namespace PICodeInfo;\n\n"; - if (!only_enums) { + if (streams || texts) { PIVector incf = inc_files.toVector(); piForeachC (PIString & i, incf) { if (i != parser.mainFile()) f << "#include \"" << i << "\"\n"; } f << "\n"; + } + /* PIString entry, argtype, rettype, args; piForeachC (PICodeParser::Entity * e, parser.entities) { if (e->name.find("::") >= 0 || e->name.startsWith("_PI")) continue; @@ -176,26 +220,35 @@ void writeModel(PICodeParser & parser, const PIString out, bool only_enums) { << e->type << " \\\"" << e->name << "\\\"!\";\n\treturn PIVariant();\n}\n"; ventities << e; } + */ + if (meta) { + f << "\n\n// Metainformation\n\n__ClassInfo_" << defname << "_Initializer__::__ClassInfo_" << defname << "_Initializer__() {\n"; + f << "\tif (_inited_) return;\n\t_inited_ = true;\n\n"; + //if (!enums) + f << "\tClassInfo * ci;\n\tTypeInfo * ni;\n\tFunctionInfo * fi;\n"; + f << "\tEnumInfo * ei;\n"; + f << "\t(*enumsInfo)[\"\"] = new EnumInfo();\n"; + //if (!enums) { + f << "\n\n// Classes\n"; + piForeachC (PICodeParser::Entity * e, parser.entities) { + if (e->name.startsWith("_PI")) continue; + makeClassInfo(f, e); + } + //} + f << "\n// Enums\n"; + piForeachC (PICodeParser::Enum & e, parser.enums) + makeEnumInfo(f, &e); + f << "}\n"; + f << "\n\nbool __ClassInfo_" << defname << "_Initializer__::_inited_ = false;\n"; } - - f << "\n\n__ClassInfo_" << defname << "_Initializer__::__ClassInfo_" << defname << "_Initializer__() {\n"; - f << "\tif (_inited_) return;\n\t_inited_ = true;\n\n"; - if (!only_enums) - f << "\tClassInfo * ci;\n\tTypeInfo * ni;\n\tFunctionInfo * fi;\n"; - f << "\tEnumInfo * ei;\n"; - f << "\t(*enumsInfo)[\"\"] = new EnumInfo();\n"; - if (!only_enums) { - f << "\n\n// Classes\n"; + if (streams) { + f << "\n\n// Stream operators\n"; piForeachC (PICodeParser::Entity * e, parser.entities) { if (e->name.startsWith("_PI")) continue; - makeClassInfo(f, e); + makeClassStream(f, e); } } - f << "\n// Enums\n"; - piForeachC (PICodeParser::Enum & e, parser.enums) - makeEnumInfo(f, &e); - f << "}\n"; - f << "\n\nbool __ClassInfo_" << defname << "_Initializer__::_inited_ = false;\n"; + f.close(); @@ -205,7 +258,7 @@ void writeModel(PICodeParser & parser, const PIString out, bool only_enums) { f << "// Generated by \"PIP Code model generator\" " << PIDateTime::current().toString("dd.MM.yyyy hh:mm:ss\n\n"); f << "#ifndef " << defname << "\n#define " << defname << "\n\n"; f << "#include \"pivariant.h\"\n#include \"picodeinfo.h\""; - if (!only_enums) { + /* f << "\n\n"; piForeachC (PICodeParser::Entity * e, ventities) f << e->type << " " << e->name << ";\n"; @@ -214,10 +267,19 @@ void writeModel(PICodeParser & parser, const PIString out, bool only_enums) { f << "\nPIVariant execFunction(" << e->name << " * object, const char * function, const PIVariant & arg0 = PIVariant(), \ const PIVariant & arg1 = PIVariant(), const PIVariant & arg2 = PIVariant(), const PIVariant & arg3 = PIVariant());"; } + */ + if (meta) { + f << "\n\n// Metainformation\n\nclass __ClassInfo_" << defname << "_Initializer__ {\n"; + f << "public:\n\t__ClassInfo_" << defname << "_Initializer__();\n\tstatic bool _inited_;\n};\n"; + f << "\nstatic __ClassInfo_" << defname << "_Initializer__ __classinfo_" << defname.toLowerCase() << "_initializer__;\n"; + } + if (streams) { + f << "\n\n// Stream operators\n"; + piForeachC (PICodeParser::Entity * e, parser.entities) { + if (e->name.startsWith("_PI")) continue; + makeClassStreamHeader(f, e); + } } - f << "\n\n\nclass __ClassInfo_" << defname << "_Initializer__ {\n"; - f << "public:\n\t__ClassInfo_" << defname << "_Initializer__();\n\tstatic bool _inited_;\n};\n"; - f << "\nstatic __ClassInfo_" << defname << "_Initializer__ __classinfo_" << defname.toLowerCase() << "_initializer__;\n"; f << "\n\n#endif // " << defname << "\n"; f.close(); } @@ -229,7 +291,11 @@ int main(int argc, char * argv[]) { cli.addArgument("output", true); cli.addArgument("help"); cli.addArgument("quiet"); + cli.addArgument("All"); + cli.addArgument("Metainfo"); cli.addArgument("Enum"); + cli.addArgument("Stream"); + cli.addArgument("Text"); cli.addArgument("print"); cli.addArgument("Print"); cli.addArgument("single"); @@ -250,7 +316,11 @@ int main(int argc, char * argv[]) { parser.parseFiles(files, !cli.hasArgument("single")); piCout << Cyan << Bold << "Parsing done"; piCout << Cyan << Bold << "Writing code model ..."; - writeModel(parser, cli.argumentValue("output"), cli.hasArgument("Enum")); + bool all = cli.hasArgument("All"); + writeModel(parser, cli.argumentValue("output"), cli.hasArgument("Metainfo") || all, + cli.hasArgument("Enum") || all, + cli.hasArgument("Stream") || all, + cli.hasArgument("Text") || all); piCout << Cyan << Bold << "Writing done"; if (cli.hasArgument("print") || cli.hasArgument("Print")) { bool womain = cli.hasArgument("print");