daily pastebin goal
83%
SHARE
TWEET

Untitled

a guest Sep 23rd, 2018 65 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #ifndef _CPP_HEADER_CODE_GENERATOR_H_
  2. #define _CPP_HEADER_CODE_GENERATOR_H_
  3.  
  4. #include "CodeGenerator.h"
  5.  
  6. struct CppHeaderGenerator {
  7.     enum {
  8.         EAccess_Public    = 0x01,
  9.         EAccess_Protected = 0x02,
  10.         EAccess_Private   = 0x04
  11.     };
  12.  
  13.     ModuleDescription* m_ModuleDescription;
  14.     fstream            m_OutputStream;
  15.  
  16.     CppHeaderGenerator(ModuleDescription* mod)
  17.         :m_ModuleDescription(mod)
  18.     {}
  19.  
  20.     int Initial(const char* outfilepath);
  21.     int Generate();
  22.     int Finalize();
  23.  
  24.     void GenerateMethod(std::list<TypeDescription>::iterator& type, int access, bool out_access=true);
  25.     void GenerateField(std::list<TypeDescription>::iterator& type, int access);
  26. };
  27.  
  28.  
  29. inline int CppHeaderGenerator::Initial(const char* typefilepath)
  30. {
  31.     char outfilepath[MAX_OUTPUT_PATH_LEN] = "";
  32.     strcpy( outfilepath, typefilepath );
  33.     char* ptr = strrchr(outfilepath, '.');
  34.     strcpy(ptr, ".h");
  35.  
  36.     m_OutputStream.open(outfilepath, fstream::out);
  37.     return 0;
  38. }
  39.  
  40. inline int CppHeaderGenerator::Finalize()
  41. {
  42.     m_OutputStream.close();
  43.     return 0;
  44. }
  45.  
  46. inline void CppHeaderGenerator::GenerateField(std::list<TypeDescription>::iterator& type, int access)
  47. {
  48.     bool pre_outed = false;
  49.     for( std::list<FieldDescription>::iterator field = type->m_Fields.begin();
  50.         field!=type->m_Fields.end(); ++field ) {
  51.             int access_flag = 0;
  52.             if( 0==strcmp(field->m_Access, "public") )
  53.                 access_flag = EAccess_Public;
  54.             else if( 0==strcmp(field->m_Access, "protected") )
  55.                 access_flag = EAccess_Protected;
  56.             else if( 0==strcmp(field->m_Access, "private") )
  57.                 access_flag = EAccess_Private;
  58.             if( 0==(access_flag&access) )
  59.                 continue;
  60.  
  61.             if( !pre_outed ) {
  62.                 if( (access&EAccess_Private) )
  63.                     m_OutputStream << "private:";
  64.                 else if( (access&EAccess_Protected) )
  65.                     m_OutputStream << "protected:";
  66.                 else if( (access&EAccess_Public) )
  67.                     m_OutputStream << "public:";
  68.                 m_OutputStream <<"\n";
  69.                 pre_outed = true;
  70.             }
  71.  
  72.             m_OutputStream << "    ";
  73.             if(field->m_IsStatic)
  74.                 m_OutputStream << "static ";
  75.  
  76.             m_OutputStream << field->m_TypeName << " " << field->m_Name << ";\n";
  77.     }
  78. }
  79.  
  80. inline void CppHeaderGenerator::GenerateMethod(std::list<TypeDescription>::iterator& type, int access, bool out_access/*=true*/) {
  81.     bool pre_outed = !out_access;
  82.     for( std::list<MethodDescription>::iterator method = type->m_Methods.begin();
  83.         method!=type->m_Methods.end(); ++method ) {
  84.             int access_flag = 0;
  85.             if( 0==strcmp(method->m_Access, "public") )
  86.                 access_flag = EAccess_Public;
  87.             else if( 0==strcmp(method->m_Access, "protected") )
  88.                 access_flag = EAccess_Protected;
  89.             else if( 0==strcmp(method->m_Access, "private") )
  90.                 access_flag = EAccess_Private;
  91.             if( 0==(access_flag&access) )
  92.                 continue;
  93.  
  94.             if( !pre_outed ) {
  95.                 if( (access&EAccess_Private) )
  96.                     m_OutputStream << "private:";
  97.                 else if( (access&EAccess_Protected) )
  98.                     m_OutputStream << "protected:";
  99.                 else if( (access&EAccess_Public) )
  100.                     m_OutputStream << "public:";
  101.                 m_OutputStream <<"\n";
  102.                 pre_outed = true;
  103.             }
  104.             if( method->m_IsStatic && method->m_Virtual ) {
  105.                 printf("Error: method[%s] can't be static and virtual at same time.\n", method->m_Name);
  106.             }
  107.             m_OutputStream << "    ";
  108.             if(method->m_IsStatic)
  109.                 m_OutputStream << "static ";
  110.             if(method->m_Virtual )
  111.                 m_OutputStream << "virtual ";
  112.             m_OutputStream << method->m_ReturnTypeName << " " << method->m_Name << "(";
  113.             for(std::list<ParameterDescription>::iterator parameter = method->m_Parmeters.begin();
  114.                 parameter!=method->m_Parmeters.end(); ++parameter ) {
  115.                     if(parameter!=method->m_Parmeters.begin()) {
  116.                         m_OutputStream << ", ";
  117.                     }
  118.                     m_OutputStream << parameter->m_TypeName << " " << parameter->m_Name;
  119.             }
  120.             m_OutputStream << ")";
  121.             if(method->m_MustImplement ) {
  122.                 m_OutputStream << " = 0";
  123.             }
  124.             m_OutputStream << ";\n";
  125.     }
  126. }
  127.  
  128. inline int CppHeaderGenerator::Generate()
  129. {
  130.     char import_package[1024];
  131.     strcpy( import_package, m_ModuleDescription->m_ImportPackage);
  132.     char* pch = strtok(import_package, " ,");
  133.     if( pch ) {
  134.         while( pch ) {
  135.             m_OutputStream << "#include\"" << pch << ".h\"\n";
  136.             pch = strtok(0, " ,");
  137.         }
  138.         m_OutputStream << "\n";
  139.     }
  140.  
  141.     /**
  142.     * generate header file
  143.     */
  144.     for( std::list<TypeDescription>::iterator type = m_ModuleDescription->m_Types.begin();
  145.         type!=m_ModuleDescription->m_Types.end(); ++ type ) {
  146.         const char* type_name = type->m_TypeName;
  147.         /**
  148.         * enum
  149.         */
  150.         if( 0==strcmp(type_name, "enum") ) {
  151.             m_OutputStream << "enum " << type->m_Name << " {\n";
  152.             for( std::list<EnumItemDescription>::iterator enum_item = type->m_EnumItems.begin();
  153.                 enum_item!=type->m_EnumItems.end(); ++enum_item ) {
  154.                     m_OutputStream << "    " << enum_item->m_Name;
  155.                     m_OutputStream << " = " << enum_item->m_Value;
  156.                     m_OutputStream << (enum_item!=type->m_EnumItems.end() ? ",\n" : "\n");
  157.             }
  158.             m_OutputStream << "};\n";
  159.             m_OutputStream << "extern EnumType* MT" << type->m_Name << ";\n\n";
  160.         } else
  161.         /**
  162.         * interface
  163.         */
  164.         if( 0==strcmp(type_name, "interface") ) {
  165.             m_OutputStream << "struct " << type->m_Name;
  166.             char extands[256];
  167.             strcpy(extands, type->m_Extands);
  168.             if( 0!=strlen(extands)) {                  
  169.                 char* pch = strtok(extands, " ,");
  170.                 if( pch ) {
  171.                     m_OutputStream << " : public ";
  172.                     while( pch!=0 ) {
  173.                         m_OutputStream << pch;
  174.                         pch = strtok(0, " ,");
  175.                         if( pch!=0 ) {
  176.                             m_OutputStream << ", public ";
  177.                         }
  178.                     }
  179.                 }
  180.             }              
  181.             m_OutputStream << "{\n";
  182.             GenerateMethod(type, EAccess_Public, false);
  183.             m_OutputStream << "};\n";
  184.             m_OutputStream << "extern InterfaceType* MT" << type->m_Name << ";\n\n";
  185.         } else
  186.         /**
  187.         * class
  188.         */
  189.         if( 0==strcmp(type_name, "class") || 0==strcmp(type_name, "object") ) {
  190.             m_OutputStream << "class " << type->m_Name;
  191.             char extands[256];
  192.             strcpy(extands, type->m_Extands);
  193.             if( 0!=strlen(extands)) {                  
  194.                 char* pch = strtok(extands, " ,");
  195.                 if( pch ) {
  196.                     m_OutputStream << " : public ";
  197.                     while( pch!=0 ) {
  198.                         m_OutputStream << pch;
  199.                         pch = strtok(0, " ,");
  200.                         if( pch!=0 ) {
  201.                             m_OutputStream << ", public ";
  202.                         }
  203.                     }
  204.                 }
  205.             } else if( 0==strcmp(type_name, "object") ) {
  206.                 m_OutputStream << " : public Object ";
  207.             }
  208.             m_OutputStream << "{\n";
  209.             GenerateField(type, EAccess_Private);
  210.             GenerateField(type, EAccess_Protected);
  211.             GenerateField(type, EAccess_Public);
  212.             m_OutputStream << "\n";
  213.  
  214.             GenerateMethod(type, EAccess_Private);
  215.             GenerateMethod(type, EAccess_Protected);
  216.             GenerateMethod(type, EAccess_Public);
  217.             m_OutputStream << "};\n";
  218.             m_OutputStream << "extern ClassType* MT" << type->m_Name << ";\n\n";
  219.         } else
  220.         /**
  221.         * valuable type
  222.         */
  223.         {
  224.             if( 0!=strcmp(type->m_Name, type->m_TypeName) ) //define on for redefinition
  225.                 m_OutputStream << "typedef " << type->m_TypeName << " " << type->m_Name << ";\n";
  226.             m_OutputStream << "extern Type* MT" << type->m_Name << ";\n\n";
  227.         }
  228.     }
  229.     return 0;
  230. }
  231.  
  232.  
  233. #endif //_CPP_HEADER_CODE_GENERATOR_H_
  234.  
  235.  
  236. #ifndef _CPP_SOURCE_CODE_GENERATOR_H_
  237. #define _CPP_SOURCE_CODE_GENERATOR_H_
  238.  
  239. #include "CodeGenerator.h"
  240.  
  241. struct CppSourceGenerator {
  242.     enum {
  243.         EAccess_Public    = 0x01,
  244.         EAccess_Protected = 0x02,
  245.         EAccess_Private   = 0x04
  246.     };
  247.  
  248.     ModuleDescription* m_ModuleDescription;
  249.     fstream  m_OutputStream;
  250.     char     m_HeaderFilePath[MAX_OUTPUT_PATH_LEN];
  251.  
  252.     CppSourceGenerator(ModuleDescription* mod)
  253.         :m_ModuleDescription(mod)
  254.     {}
  255.  
  256.     int Initial(const char* outfilepath);
  257.     int Finalize();
  258.     int Generate();
  259. };
  260.  
  261.  
  262. inline int CppSourceGenerator::Initial(const char* typefilepath)
  263. {
  264.     char outfilepath[MAX_OUTPUT_PATH_LEN] = "";
  265.     strcpy( outfilepath, typefilepath );
  266.     char* ptr = strrchr(outfilepath, '.');
  267.     strcpy(ptr, ".cpp");
  268.  
  269.     char* ptr_pre0 = strrchr(outfilepath, '/');
  270.     char* ptr_pre1 = strrchr(outfilepath, '\\');
  271.     if( ptr_pre0 ) {
  272.         strcpy( m_HeaderFilePath, ptr_pre0+1 );
  273.     } else if( ptr_pre1 ){
  274.         strcpy( m_HeaderFilePath, ptr_pre1+1 );
  275.     } else {
  276.         strcpy( m_HeaderFilePath, outfilepath );
  277.     }  
  278.     ptr = strrchr(m_HeaderFilePath, '.');
  279.     strcpy(ptr, ".h"); 
  280.  
  281.     m_OutputStream.open(outfilepath, fstream::out);
  282.     return 0;
  283. }
  284.  
  285. inline int CppSourceGenerator::Finalize()
  286. {
  287.     m_OutputStream.close();
  288.     return 0;
  289. }
  290.  
  291. inline int CppSourceGenerator::Generate()
  292. {
  293.     m_OutputStream << "#include \"ReflectionSystemImp.h\"\n";
  294.     m_OutputStream << "#include \"" << m_HeaderFilePath << "\"\n\n\n";
  295.  
  296.     for( std::list<TypeDescription>::iterator type = m_ModuleDescription->m_Types.begin();
  297.         type!=m_ModuleDescription->m_Types.end(); ++type ) {
  298.             const char* type_name = type->m_TypeName;
  299.             /**
  300.             * enum
  301.             */
  302.             if( 0==strcmp(type_name, "enum") ) {
  303.                 size_t enum_item_count = 0;
  304.                 m_OutputStream << "static EnumItem s_Enum_" << type->m_Name << "_Items[] = {\n";
  305.                 for( std::list<EnumItemDescription>::iterator enum_item = type->m_EnumItems.begin();
  306.                     enum_item!=type->m_EnumItems.end(); ++enum_item ) {
  307.                         m_OutputStream << "    {\"" << enum_item->m_Name << "\", " << enum_item->m_Value;
  308.                         m_OutputStream << (enum_item!=type->m_EnumItems.end() ? "},\n" : "}\n");
  309.                         ++enum_item_count;
  310.                 }
  311.                 m_OutputStream << "};\n";
  312.                 m_OutputStream << "EnumTypeImp s_Enum_" << type->m_Name << "_Type(\"" << type->m_Name << "\", "
  313.                     << "sizeof(" << type->m_Name << "), " << enum_item_count << ", " << "&s_Enum_"
  314.                     << type->m_Name << "_Items[0]);\n";
  315.                 m_OutputStream << "EnumType* MT" << type->m_Name << " = &s_Enum_" << type->m_Name << "_Type;\n\n";
  316.             } else
  317.             /**
  318.             * interface
  319.             */
  320.             if( 0==strcmp(type_name, "interface") ) {
  321.                 // parameters
  322.                 for(std::list<MethodDescription>::iterator method = type->m_Methods.begin(); method!=type->m_Methods.end(); ++method ) {
  323.                     m_OutputStream << "struct {\n";
  324.                     for(std::list<ParameterDescription>::iterator paramter = method->m_Parmeters.begin(); paramter!=method->m_Parmeters.end(); ++paramter ){
  325.                         m_OutputStream << "    " << paramter->m_TypeName << " " << paramter->m_Name << ";\n";
  326.                     }
  327.                     m_OutputStream << "} s_" << type->m_Name << "_" << method->m_Name << "_ParamContext;\n";
  328.                     m_OutputStream << "static ParameterItem s_" << type->m_Name << "_" << method->m_Name << "_Params[] = {\n";
  329.                     for(std::list<ParameterDescription>::iterator paramter = method->m_Parmeters.begin(); paramter!=method->m_Parmeters.end();  ){
  330.                         m_OutputStream << "    {MT" << paramter->m_TypeName << ", "
  331.                             << (paramter->m_Optional ? "true" : "false")
  332.                             << ", \"" << paramter->m_Name << "\""
  333.                             << ", &" << "s_" << type->m_Name << "_" << method->m_Name << "_ParamContext." << paramter->m_Name
  334.                             << ", \"" << paramter->m_DefaultValue << "\"";
  335.                         ++paramter;
  336.                         m_OutputStream << (paramter==method->m_Parmeters.end() ? "}\n" : "},\n");
  337.                     }
  338.                     m_OutputStream << "};\n";
  339.                 }
  340.  
  341.                 // method              
  342.                 m_OutputStream << "static MethodItem s_" << type->m_Name << "_Methods[] = {\n";
  343.                 for(std::list<MethodDescription>::iterator method = type->m_Methods.begin(); method!=type->m_Methods.end();  )
  344.                 {
  345.                     m_OutputStream << "    {sizeof(s_" << type->m_Name << "_" << method->m_Name << "_Params)/sizeof(MethodItem)"
  346.                         << ", &s_" << type->m_Name << "_" << method->m_Name << "_Params";
  347.                     if( 0==strcmp(method->m_Access, "private") ) {
  348.                         m_OutputStream << ", FLAG_ACCESS_PRIVATE";
  349.                     } else if( 0==strcmp(method->m_Access, "protected") ) {
  350.                         m_OutputStream << ", FLAG_ACCESS_PROTECTED";
  351.                     } else {
  352.                         m_OutputStream << ", FLAG_ACCESS_PUBLIC";
  353.                     }
  354.                     if( method->m_IsConstructor ) {
  355.                         m_OutputStream << "|METHOD_FLAG_CONSTRUCTOR_MASK";
  356.                     }
  357.                     if( method->m_Virtual ) {
  358.                         m_OutputStream << "|METHOD_FLAG_VIRTUAL_MASK";
  359.                     }
  360.                     if( method->m_IsStatic ) {
  361.                         m_OutputStream << "|METHOD_FLAG_STATIC_MASK";
  362.                     }
  363.                     ++method;
  364.                     m_OutputStream << (method==type->m_Methods.end() ? "}\n" : "},\n");                    
  365.                 }
  366.                 m_OutputStream << "};\n";
  367.  
  368.                 // method caller
  369.                 size_t method_item_count = 0;
  370.                 for(std::list<MethodDescription>::iterator method = type->m_Methods.begin(); method!=type->m_Methods.end(); ++method  )
  371.                 {
  372.                     m_OutputStream << "struct " << type->m_Name << "_" << method->m_Name << "_Caller : public MethodInfoImp {\n"
  373.                         <<"    " << type->m_Name << "_" << method->m_Name << "_Caller():MethodInfoImp(" << "&s_" << type->m_Name << "_Methods[" << method_item_count << "]) {}\n";
  374.                     m_OutputStream << "    virtual int Invoke(void* obj) {\n        " << type->m_Name << "* o = (" << type->m_Name << "*)obj;\n"
  375.                         << "        o->" << method->m_Name << "(";
  376.                     for(std::list<ParameterDescription>::iterator paramter = method->m_Parmeters.begin(); paramter!=method->m_Parmeters.end();  ){
  377.                         m_OutputStream << "s_" << type->m_Name << "_" << method->m_Name << "_ParamContext." << paramter->m_Name;
  378.                         ++paramter;
  379.                         if( paramter!=method->m_Parmeters.end() )
  380.                             m_OutputStream << ", ";
  381.                     }
  382.                     m_OutputStream << ");\n    }\n} s_" << type->m_Name << "_" << method->m_Name << "_Caller;\n";
  383.                     ++method_item_count;
  384.                 }
  385.                 m_OutputStream << "MethodInfo* s_" << type->m_Name << "_Callers[] = {";
  386.                 for(std::list<MethodDescription>::iterator method = type->m_Methods.begin(); method!=type->m_Methods.end(); )
  387.                 {
  388.                     m_OutputStream << "&s_" << type->m_Name << "_" << method->m_Name << "_Caller";
  389.                     ++method;
  390.                     if( method!=type->m_Methods.end() )
  391.                         m_OutputStream << ", ";
  392.                 }
  393.                 m_OutputStream << "};\n";
  394.  
  395.                 // base type
  396.                 m_OutputStream << "static Interface* s_" << type->m_Name << "_Bases[] = {";
  397.                 char extands[256];
  398.                 int base_count = 0;
  399.                 strcpy(extands, type->m_Extands);
  400.                 if( 0!=strlen(extands)) {                  
  401.                     char* pch = strtok(extands, " ,");
  402.                     while( 0!=pch ) {
  403.                         m_OutputStream << "MT" <<pch;
  404.                         ++base_count;
  405.                         pch = strtok(0, " ,");
  406.                         if( 0!=pch )
  407.                             m_OutputStream << ", ";
  408.                     }
  409.                 }
  410.                 m_OutputStream << "};\n";
  411.  
  412.                 m_OutputStream << "struct Interface" << type->m_Name << " : public InterfaceTypeImp {";
  413.                 m_OutputStream << "};\n";
  414.                 m_OutputStream << "static InterfaceTypeImp s_Interface_" << type->m_Name << "_Type("
  415.                     << type->m_Name << ", " << base_count << ", s_" << type->m_Name << "_Bases&[0], "
  416.                     << method_item_count << ", &s_" << type->m_Name << "_Callers[0]);\n\n";
  417.                
  418.             } else
  419.             /**
  420.             * class
  421.             */
  422.             if( 0==strcmp(type_name, "class") || 0==strcmp(type_name, "object") ) {
  423.                 // parameters
  424.                 for(std::list<MethodDescription>::iterator method = type->m_Methods.begin(); method!=type->m_Methods.end(); ++method ) {
  425.                     m_OutputStream << "struct {\n";
  426.                     for(std::list<ParameterDescription>::iterator paramter = method->m_Parmeters.begin(); paramter!=method->m_Parmeters.end(); ++paramter ){
  427.                         m_OutputStream << "    " << paramter->m_TypeName << " " << paramter->m_Name << ";\n";
  428.                     }
  429.                     m_OutputStream << "} s_" << type->m_Name << "_" << method->m_Name << "_ParamContext;\n";
  430.                     m_OutputStream << "static ParameterItem s_" << type->m_Name << "_" << method->m_Name << "_Params[] = {\n";
  431.                     for(std::list<ParameterDescription>::iterator paramter = method->m_Parmeters.begin(); paramter!=method->m_Parmeters.end();  ){
  432.                         m_OutputStream << "    {MT" << paramter->m_TypeName << ", "
  433.                             << (paramter->m_Optional ? "true" : "false")
  434.                             << ", \"" << paramter->m_Name << "\""
  435.                             << ", &" << "s_" << type->m_Name << "_" << method->m_Name << "_ParamContext." << paramter->m_Name
  436.                             << ", \"" << paramter->m_DefaultValue << "\"";
  437.                         ++paramter;
  438.                         m_OutputStream << (paramter==method->m_Parmeters.end() ? "}\n" : "},\n");
  439.                     }
  440.                     m_OutputStream << "};\n";
  441.                 }
  442.  
  443.                 // method              
  444.                 m_OutputStream << "static MethodItem s_" << type->m_Name << "_Methods[] = {\n";
  445.                 for(std::list<MethodDescription>::iterator method = type->m_Methods.begin(); method!=type->m_Methods.end();  )
  446.                 {
  447.                     m_OutputStream << "    {sizeof(s_" << type->m_Name << "_" << method->m_Name << "_Params)/sizeof(MethodItem)"
  448.                         << ", &s_" << type->m_Name << "_" << method->m_Name << "_Params";
  449.                     if( 0==strcmp(method->m_Access, "private") ) {
  450.                         m_OutputStream << ", FLAG_ACCESS_PRIVATE";
  451.                     } else if( 0==strcmp(method->m_Access, "protected") ) {
  452.                         m_OutputStream << ", FLAG_ACCESS_PROTECTED";
  453.                     } else {
  454.                         m_OutputStream << ", FLAG_ACCESS_PUBLIC";
  455.                     }
  456.                     if( method->m_IsConstructor ) {
  457.                         m_OutputStream << "|METHOD_FLAG_CONSTRUCTOR_MASK";
  458.                     }
  459.                     if( method->m_Virtual ) {
  460.                         m_OutputStream << "|METHOD_FLAG_VIRTUAL_MASK";
  461.                     }
  462.                     if( method->m_IsStatic ) {
  463.                         m_OutputStream << "|METHOD_FLAG_STATIC_MASK";
  464.                     }
  465.                     ++method;
  466.                     m_OutputStream << (method==type->m_Methods.end() ? "}\n" : "},\n");                    
  467.                 }
  468.                 m_OutputStream << "};\n";
  469.  
  470.                 // method caller
  471.                 size_t method_item_count = 0;
  472.                 for(std::list<MethodDescription>::iterator method = type->m_Methods.begin(); method!=type->m_Methods.end(); ++method  )
  473.                 {
  474.                     m_OutputStream << "struct " << type->m_Name << "_" << method->m_Name << "_Caller : public MethodInfoImp {\n"
  475.                         <<"    " << type->m_Name << "_" << method->m_Name << "_Caller():MethodInfoImp(" << "&s_" << type->m_Name << "_Methods[" << method_item_count << "]) {}\n";
  476.                     m_OutputStream << "    virtual int Invoke(void* obj) {\n        " << type->m_Name << "* o = (" << type->m_Name << "*)obj;\n"
  477.                         << "        o->" << method->m_Name << "(";
  478.                     for(std::list<ParameterDescription>::iterator paramter = method->m_Parmeters.begin(); paramter!=method->m_Parmeters.end();  ){
  479.                         m_OutputStream << "s_" << type->m_Name << "_" << method->m_Name << "_ParamContext." << paramter->m_Name;
  480.                         ++paramter;
  481.                         if( paramter!=method->m_Parmeters.end() )
  482.                             m_OutputStream << ", ";
  483.                     }
  484.                     m_OutputStream << ");\n    }\n} s_" << type->m_Name << "_" << method->m_Name << "_Caller;\n";
  485.                     ++method_item_count;
  486.                 }
  487.                 m_OutputStream << "MethodInfo* s_" << type->m_Name << "_Callers[] = {";
  488.                 for(std::list<MethodDescription>::iterator method = type->m_Methods.begin(); method!=type->m_Methods.end(); )
  489.                 {
  490.                     m_OutputStream << "&s_" << type->m_Name << "_" << method->m_Name << "_Caller";
  491.                     ++method;
  492.                     if( method!=type->m_Methods.end() )
  493.                         m_OutputStream << ", ";
  494.                 }
  495.                 m_OutputStream << "};\n";
  496.  
  497.                 // field
  498.                 m_OutputStream << "FieldItem s_" << type->m_Name << "_Fields[] = {\n";
  499.                 for(std::list<FieldDescription>::iterator field = type->m_Fields.begin(); field!=type->m_Fields.end(); ) {
  500.                     m_OutputStream << "    {";
  501.                     if( 0==strcmp(field->m_Access, "private") ) {
  502.                         m_OutputStream << "FLAG_ACCESS_PRIVATE";
  503.                     } else if( 0==strcmp(field->m_Access, "protected") ) {
  504.                         m_OutputStream << "FLAG_ACCESS_PROTECTED";
  505.                     } else {
  506.                         m_OutputStream << "FLAG_ACCESS_PUBLIC";
  507.                     }
  508.                     if( field->m_CanWrite ) {
  509.                         m_OutputStream << "|FIELD_FLAG_WRITE_MASK";
  510.                     }
  511.                     if( field->m_CanRead ) {
  512.                         m_OutputStream << "|FIELD_FLAG_READ_MASK";
  513.                     }
  514.                     if( field->m_IsStatic ) {
  515.                         m_OutputStream << "|FIELD_FLAG_STATIC_MASK";
  516.                     }
  517.  
  518.                     m_OutputStream << ", MT" << field->m_TypeName
  519.                         << ", " << field->m_Name
  520.                         << ", " << field->m_DefaultValue;
  521.                     if( 0==strcmp(field->m_Access, "public") )
  522.                         m_OutputStream << ", offsetof(" << type->m_Name << ", " << field->m_Name << ")";
  523.                     else
  524.                         m_OutputStream << ", INVALID_OFFSET";
  525.                     ++field;
  526.                     m_OutputStream << (field!=type->m_Fields.end() ? "},\n" : "}\n");
  527.                 }
  528.                 m_OutputStream << "};\n";              
  529.  
  530.                 // base type
  531.                 m_OutputStream << "static Interface* s_" << type->m_Name << "_Bases[] = {";
  532.                 char extands[256];
  533.                 int base_count = 0;
  534.                 strcpy(extands, type->m_Extands);
  535.                 if( 0!=strlen(extands)) {                  
  536.                     char* pch = strtok(extands, " ,");
  537.                     while( 0!=pch ) {
  538.                         m_OutputStream << "MT" <<pch;
  539.                         ++base_count;
  540.                         pch = strtok(0, " ,");
  541.                         if( 0!=pch )
  542.                             m_OutputStream << ", ";
  543.                     }
  544.                 }
  545.                 m_OutputStream << "};\n";
  546.  
  547.                 m_OutputStream << "struct Interface" << type->m_Name << " : public ClassTypeImp {";
  548.                 m_OutputStream << "};\n";
  549.                 m_OutputStream << "static ClassTypeImp s_Class_" << type->m_Name << "_Type("
  550.                     << type->m_Name << ", " << base_count << ", s_" << type->m_Name << "_Bases&[0], "
  551.                     << method_item_count << ", &s_" << type->m_Name << "_Callers[0]);\n\n";
  552.             } else
  553.             /**
  554.             * valuable type
  555.             */
  556.             {
  557.                 m_OutputStream << "ValueType s_" << type->m_Name << "_Type(\"" << type->m_Name << "\", Type::REDEFINE, sizeof(" << type->m_Name << ");\n\n";
  558.             }
  559.     }
  560.  
  561.     ///**
  562.     //* generate stub source file
  563.     //*/
  564.     //for( xml_node type = m_Types.first_child(); type; type=type.next_sibling() )
  565.     //{
  566.     //  const char* type_name = type.attribute("type").value();
  567.     //  /**
  568.     //  * enum
  569.     //  */
  570.     //  if( 0==strcmp(type_name, "enum") ) {
  571.     //      size_t enum_item_count = 0;
  572.     //      m_OutputStream << "static EnumItem s_Enum_" << type.name() << "_Items[] = {\n";
  573.     //      int current_value = 0;
  574.     //      for(xml_node item=type.first_child(); item; item=item.next_sibling() )
  575.     //      {              
  576.     //          if( item.attribute("value") ) {
  577.     //              current_value =  atoi(item.attribute("value").value());
  578.     //          }
  579.     //          m_OutputStream << "    {\"" << item.name() << "\", " << current_value;
  580.     //          m_OutputStream << (item.next_sibling()? "},\n" : "}\n");
  581.     //         
  582.     //          ++current_value;
  583.     //          ++enum_item_count;
  584.     //      }
  585.     //      m_OutputStream << "};\n";
  586.  
  587.     //      m_OutputStream << "EnumTypeInfo s_Enum_" << type.name() << "_Info(\"" << type.name() << "\", " << "sizeof(" << type.name() << "), " << enum_item_count << ", " << "&s_Enum_" << type.name() << "_Items[0]);\n\n";
  588.     //  } else
  589.  //       /**
  590.     //  * struct
  591.     //  */
  592.     //  if( 0==strcmp(type_name, "struct") ) {         
  593.     //      size_t struct_item_count = 0;
  594.     //      m_OutputStream << "static StructItem s_Struct_" << type.name() << "_Items[] = {\n";
  595.     //      for(xml_node item=type.first_child(); item; item=item.next_sibling() )
  596.     //      {              
  597.     //          m_OutputStream << "    {\"" << item.name() << "\", \"" << item.attribute("type").value() << "\"";
  598.     //          m_OutputStream << (item.next_sibling()? "},\n" : "}\n");
  599.     //          ++struct_item_count;
  600.     //      }
  601.     //      m_OutputStream << "};\n";
  602.  
  603.     //      m_OutputStream << "StructTypeInfo s_Struct_" << type.name() << "_Info(\"" << type.name() << "\", " << "sizeof(" << type.name() << "), " << struct_item_count << ", " << "&s_Struct_" << type.name() << "_Items[0]);\n\n";
  604.  
  605.     //  } else
  606.     //  /**
  607.     //  * class
  608.     //  */
  609.     //  if( 0==strcmp(type_name, "class") ) {
  610.     //      // method param
  611.     //      for(xml_node item=type.first_child(); item; item=item.next_sibling() )
  612.     //      {
  613.     //          if( 0==strcmp(item.attribute("type").value(), "function") )
  614.     //          {
  615.     //              m_OutputStream << "static MethodParam s_Class_" << type.name() << "_" << item.name() << "_Params[] = {\n";
  616.     //              for( xml_node param = item.first_child(); param; param=param.next_sibling() ) {
  617.     //                  m_OutputStream << "    {\"" << param.name() << "\", \"" << param.attribute("type").value() << "\"";
  618.     //                  m_OutputStream << (param.next_sibling()? "},\n" : "}\n");
  619.     //              }
  620.     //              m_OutputStream << "};\n";
  621.     //          }
  622.     //      }          
  623.  
  624.     //      // method
  625.     //      size_t method_item_count = 0;
  626.     //      m_OutputStream << "static MethodItem s_Class_" << type.name() << "_Methods[] = {\n";
  627.     //      for(xml_node item=type.first_child(); item; item=item.next_sibling() )
  628.     //      {
  629.     //          if( 0==strcmp(item.attribute("type").value(), "function") ) {
  630.     //              m_OutputStream << "    {\"" << item.name() << "\", \"" << item.attribute("return").value() << "\""
  631.     //                     << ", sizeof(" << "s_Class_" << type.name() << "_" << item.name() << "_Params" << ")/sizeof(MethodParam),"
  632.     //                     << " &s_Class_" << type.name() << "_" << item.name() << "_Params[0]";
  633.     //              m_OutputStream << (item.next_sibling()? "},\n" : "}\n");
  634.     //              ++method_item_count;
  635.     //          }
  636.     //      }
  637.     //      m_OutputStream << "};\n";
  638.  
  639.     //      // property
  640.     //      size_t property_item_count = 0;
  641.     //      m_OutputStream << "static PropertyItem s_Class_" << type.name() << "_Propertys[] = {\n";
  642.     //      for(xml_node item=type.first_child(); item; item=item.next_sibling() )
  643.     //      {
  644.     //          if( 0!=strcmp(item.attribute("type").value(), "function") ) { // member function
  645.     //              m_OutputStream << "    {\"" << item.name() << "\", \"" << item.attribute("type").value() << "\"";
  646.     //              m_OutputStream << (item.next_sibling()? "},\n" : "}\n");
  647.     //              ++property_item_count;
  648.     //          }
  649.     //      }
  650.     //      m_OutputStream << "};\n";
  651.  
  652.     //      m_OutputStream << "ClassTypeInfo s_Class_" << type.name() << "_Info(\"" << type.name() << "\", " << "sizeof(" << type.name() << "), " << property_item_count << ", " << "&s_Class_" << type.name() << "_Propertys[0],"
  653.     //          << method_item_count << ", &s_Class_" << type.name() << "_Methods[0] );\n\n";
  654.  
  655.     //  } else
  656.     //  /**
  657.     //  * runtime class
  658.     //  */
  659.     //  if( 0==strcmp(type_name, "rtclass") ) {
  660.     //      // method param
  661.     //      for(xml_node item=type.first_child(); item; item=item.next_sibling() )
  662.     //      {
  663.     //          if( 0==strcmp(item.attribute("type").value(), "function") )
  664.     //          {
  665.     //              m_OutputStream << "static MethodParam s_Class_" << type.name() << "_" << item.name() << "_Params[] = {\n";
  666.     //              for( xml_node param = item.first_child(); param; param=param.next_sibling() ) {
  667.     //                  m_OutputStream << "    {\"" << param.name() << "\", \"" << param.attribute("type").value() << "\"";
  668.     //                  m_OutputStream << (param.next_sibling()? "},\n" : "}\n");
  669.     //              }
  670.     //              m_OutputStream << "};\n";
  671.     //          }
  672.     //      }          
  673.  
  674.     //      // method
  675.     //      size_t method_item_count = 0;
  676.     //      m_OutputStream << "static MethodItem s_Class_" << type.name() << "_Methods[] = {\n";
  677.     //      for(xml_node item=type.first_child(); item; item=item.next_sibling() )
  678.     //      {
  679.     //          if( 0==strcmp(item.attribute("type").value(), "function") ) {
  680.     //              m_OutputStream << "    {\"" << item.name() << "\", \"" << item.attribute("return").value() << "\""
  681.     //                  << ", sizeof(" << "s_Class_" << type.name() << "_" << item.name() << "_Params" << ")/sizeof(MethodParam),"
  682.     //                  << " &s_Class_" << type.name() << "_" << item.name() << "_Params[0]";
  683.     //              m_OutputStream << (item.next_sibling()? "},\n" : "}\n");
  684.     //              ++method_item_count;
  685.     //          }
  686.     //      }
  687.     //      m_OutputStream << "};\n";
  688.  
  689.     //      // property
  690.     //      size_t property_item_count = 0;
  691.     //      m_OutputStream << "static PropertyItem s_Class_" << type.name() << "_Propertys[] = {\n";
  692.     //      for(xml_node item=type.first_child(); item; item=item.next_sibling() )
  693.     //      {
  694.     //          if( 0!=strcmp(item.attribute("type").value(), "function") ) { // member function
  695.     //              m_OutputStream << "    {\"" << item.name() << "\", \"" << item.attribute("type").value() << "\"";
  696.     //              m_OutputStream << (item.next_sibling()? "},\n" : "}\n");
  697.     //              ++property_item_count;
  698.     //          }
  699.     //      }
  700.     //      m_OutputStream << "};\n";
  701.  
  702.     //      m_OutputStream << "RTClassTypeInfo s_RTClass_" << type.name() << "_Info(\"" << type.name() << "\", " << "sizeof(" << type.name() << "), " << property_item_count << ", " << "&s_Class_" << type.name() << "_Propertys[0],"
  703.     //          << method_item_count << ", &s_Class_" << type.name() << "_Methods[0] );\n\n";
  704.  
  705.     //  } else
  706.     //  /**
  707.     //  * basic type
  708.     //  */
  709.     //  {
  710.     //      m_OutputStream << "BasicTypeInfo s_Basic_" << type.name() << "_Info(\"" << type.name() << "\", " << "sizeof(" << type.name() << "), \"" << type.attribute("type").value() << "\");\n\n";
  711.     //  }
  712.     //}
  713.     return 0;
  714. }
  715.  
  716.  
  717. #endif
  718.  
  719.  
  720. #pragma once
  721.  
  722. #include <list>
  723. #include <cstring>
  724. #include <iostream>
  725. #include <fstream>
  726. #include <cstdarg>
  727. #include <cstdio>
  728. using namespace std;
  729.  
  730. #include "pugixml.hpp"
  731. using namespace pugi;
  732.  
  733. struct ValueTypeDescription {
  734.     const char* m_Name;
  735.     const char* m_TypeName;
  736. };
  737.  
  738. struct EnumItemDescription {
  739.     const char* m_Name;
  740.     int         m_Value;
  741. };
  742.  
  743. struct FieldDescription {
  744.     const char* m_Name;
  745.     const char* m_TypeName;
  746.     const char* m_Access;
  747.     bool        m_IsStatic;
  748.     bool        m_CanRead;
  749.     bool        m_CanWrite;
  750.     const char* m_DefaultValue;
  751. };
  752.  
  753. struct ParameterDescription {
  754.     const char* m_Name;
  755.     const char* m_TypeName;
  756.     bool        m_Optional;
  757.     const char* m_DefaultValue;
  758. };
  759.  
  760. struct MethodDescription {
  761.     const char* m_Name;
  762.     const char* m_Access;
  763.     bool        m_IsStatic;
  764.     bool        m_IsConstructor;
  765.     bool        m_Virtual;
  766.     bool        m_MustImplement;
  767.     const char* m_ReturnTypeName;
  768.     std::list<ParameterDescription> m_Parmeters;
  769. };
  770.  
  771. struct TypeDescription {
  772.     const char* m_Name;
  773.     const char* m_TypeName;
  774.  
  775.     const char* m_Extands;
  776.     const char* m_Implements;
  777.  
  778.     int                            m_ArrayBound;
  779.     std::list<EnumItemDescription> m_EnumItems;
  780.     std::list<FieldDescription>    m_Fields;
  781.     std::list<MethodDescription>   m_Methods;
  782. };
  783.  
  784. struct ModuleDescription {
  785.    const char* m_Name;
  786.    const char* m_Description;
  787.    const char* m_Activator;
  788.    const char* m_Version;
  789.    const char* m_ImportPackage;
  790.    const char* m_ExportPackage;
  791.  
  792.    std::list<TypeDescription> m_Types;
  793.  
  794.    int ParserModule(xml_node &node);
  795. };
  796.  
  797.  
  798. #include "GrammarTree.h"
  799.  
  800.  
  801. int ParserValueType(xml_node &node, TypeDescription &type_desc);
  802. int ParserEnum(xml_node &node, TypeDescription &type_desc);
  803. int ParserInterface(xml_node &node, TypeDescription &type_desc);
  804. int ParserClass(xml_node &node, TypeDescription &type_desc);
  805. int ParserObject(xml_node &node, TypeDescription &type_desc);
  806.  
  807. int ModuleDescription::ParserModule(xml_node &node)
  808. {  
  809.     m_Name = node.name();
  810.     m_Description = node.attribute("description").value();
  811.     m_Activator = node.attribute("activator").value();
  812.     m_Version = node.attribute("version").value();
  813.     m_ImportPackage = node.attribute("import_package").value();
  814.     m_ExportPackage = node.attribute("export_package").value();
  815.  
  816.  
  817.     for( xml_node type = node.first_child(); type; type=type.next_sibling() )
  818.     {
  819.         int error = 0;
  820.         TypeDescription type_desc;
  821.         type_desc.m_Name = type.name();
  822.         const char* type_name = type.attribute("type").value();
  823.         type_desc.m_TypeName = type_name;
  824.         /**
  825.         * enum
  826.         */
  827.         if( 0==strcmp(type_name, "enum") ) {
  828.             error = ParserEnum(type, type_desc);
  829.         } else
  830.         /**
  831.         * interface
  832.         */
  833.         if( 0==strcmp(type_name, "interface") ) {
  834.            error = ParserInterface(type, type_desc);
  835.         } else
  836.         /**
  837.         * class
  838.         */
  839.         if( 0==strcmp(type_name, "class") ) {
  840.             error = ParserClass(type, type_desc);
  841.         } else
  842.         /**
  843.         * object class
  844.         */
  845.         if( 0==strcmp(type_name, "object") ) {
  846.             error = ParserObject(type, type_desc);
  847.         } else
  848.         /**
  849.         * value type
  850.         */
  851.         {
  852.             error = ParserValueType(type, type_desc);
  853.         }
  854.         if( 0!=error )
  855.             return error;
  856.         m_Types.push_back(type_desc);
  857.     }
  858.     return 0;
  859. }
  860.  
  861. int ParserValueType(xml_node &node, TypeDescription &type_desc)
  862. {
  863.     // no need other operation
  864.     return 0;
  865. }
  866.  
  867. int ParserEnum(xml_node &type, TypeDescription &type_desc)
  868. {
  869.     EnumItemDescription enum_item;
  870.     int current_item_value = 0;
  871.     for(xml_node item=type.first_child(); item; item=item.next_sibling() )
  872.     {
  873.         enum_item.m_Name = item.name();
  874.         if( item.attribute("value") ) {
  875.             current_item_value = atoi(item.attribute("value").value());
  876.         }
  877.         enum_item.m_Value = current_item_value++;
  878.         type_desc.m_EnumItems.push_back(enum_item);
  879.     }
  880.     return 0;
  881. }
  882.  
  883. int ParserInterface(xml_node &type, TypeDescription &type_desc)
  884. {
  885.     ParameterDescription param;
  886.     MethodDescription    method;
  887.  
  888.     type_desc.m_Extands = type.attribute("extands") ? type.attribute("extands").value() : "";
  889.     type_desc.m_Implements = "";
  890.     for(xml_node item=type.first_child(); item; item=item.next_sibling() )
  891.     {  
  892.         if( 0==strcmp(item.attribute("type").value(), "function") ) { // method
  893.             method.m_Name = item.name();
  894.             method.m_Access = "public";
  895.             method.m_IsConstructor = false;
  896.             method.m_ReturnTypeName = !method.m_IsConstructor ? item.attribute("return").value() : "";
  897.             method.m_IsStatic = false;
  898.             method.m_Virtual = true;
  899.             method.m_MustImplement = true;
  900.             method.m_Parmeters.clear();
  901.             for(xml_node param_node=item.first_child(); param_node; param_node=param_node.next_sibling() ) {
  902.                 param.m_Name = param_node.name();
  903.                 param.m_TypeName = param_node.attribute("type").value();
  904.                 param.m_Optional = false;
  905.                 param.m_DefaultValue = "";
  906.                 method.m_Parmeters.push_back(param);
  907.             }
  908.             type_desc.m_Methods.push_back(method);
  909.         }
  910.     }
  911.     return 0;
  912. }
  913.  
  914. int ParserClass(xml_node &type, TypeDescription &type_desc)
  915. {
  916.     ParameterDescription param;
  917.     MethodDescription    method;
  918.     FieldDescription     field;
  919.  
  920.     type_desc.m_Extands = type.attribute("extands") ? type.attribute("extands").value() : "";
  921.     type_desc.m_Implements = type.attribute("implements") ? type.attribute("implements").value() : "";
  922.  
  923.     for(xml_node item=type.first_child(); item; item=item.next_sibling() )
  924.     {  
  925.         if( 0==strcmp(item.attribute("type").value(), "function") ) { // method
  926.             method.m_Name = item.name();
  927.             method.m_Access = item.attribute("access") ? item.attribute("access").value() : "public";
  928.             method.m_IsConstructor = (0==strcmp(type_desc.m_Name, method.m_Name));
  929.             method.m_ReturnTypeName = !method.m_IsConstructor ? item.attribute("return").value() : "";
  930.             method.m_IsStatic = item.attribute("static") ? true : false;
  931.             method.m_Virtual = item.attribute("virtual") ? true : false;
  932.             method.m_MustImplement = item.attribute("pure") ? true :false;
  933.             method.m_Parmeters.clear();
  934.             for(xml_node param_node=item.first_child(); param_node; param_node=param_node.next_sibling() ) {
  935.                 param.m_Name = param_node.name();
  936.                 param.m_TypeName = param_node.attribute("type").value();
  937.                 param.m_Optional = param_node.attribute("optional") ? true : false;
  938.                 param.m_DefaultValue = param.m_Optional ? param_node.attribute("default").value() : "";
  939.                 method.m_Parmeters.push_back(param);
  940.             }
  941.             type_desc.m_Methods.push_back(method);
  942.         } else {                                                      // field
  943.             field.m_Name = item.name();
  944.             field.m_TypeName = item.attribute("type").value();
  945.             field.m_Access = item.attribute("access") ? item.attribute("access").value() : "public";
  946.             field.m_IsStatic = item.attribute("static") ? true : false;
  947.             field.m_CanRead = item.attribute("noread") ? false : true;
  948.             field.m_CanWrite = item.attribute("nowrite") ? false : true;
  949.             field.m_DefaultValue = item.attribute("default").value();
  950.             type_desc.m_Fields.push_back(field);
  951.         }
  952.     }
  953.     return 0;
  954. }
  955.  
  956. int ParserObject(xml_node &node, TypeDescription &type_desc)
  957. {
  958.     ParserClass(node, type_desc);
  959.     return 0;
  960. }
  961.  
  962.  
  963. #pragma warning(disable:4996)
  964.  
  965.  
  966.  
  967.  
  968.  
  969. #include "CppHeaderCodeGenerator.h"
  970. #include "CppSourceCodeGenerator.h"
  971.  
  972.  
  973. int main( int argc, char* argv[] )
  974. {
  975.     /**
  976.     * parser typedef file
  977.     */
  978.     xml_document doc;
  979.     xml_parse_result result = doc.load_file(argv[1]);  
  980.    
  981.     if( result ) {
  982.         cout << "Type file[" << argv[1] << "] parsed with no errors." << endl;
  983.     }else {
  984.         cout << "Type file[" << argv[1] << "] parsed with error, attr value: [" << doc.child("node").attribute("attr").value() << "]\n";
  985.         cout << "Error description: " << result.description() << "\n";
  986.         return -1;
  987.     }
  988.  
  989.     xml_node module_node = doc.root().first_child();
  990.  
  991.     /**
  992.     * parser grammar tree
  993.     */
  994.     ModuleDescription module;
  995.     module.ParserModule(module_node);
  996.  
  997.     /**
  998.     * generate header files and stub source file
  999.     */
  1000.     int ret = 0;
  1001.  
  1002.     while( true )
  1003.     {
  1004.         cout << "Generate c++ header file." << endl;
  1005.         CppHeaderGenerator headerGen(&module);
  1006.         if( 0==headerGen.Initial(argv[1]) ) {
  1007.             if( 0!=headerGen.Generate() )
  1008.                 ret = -2;
  1009.             if( 0!=headerGen.Finalize() )
  1010.                 ret = -2;
  1011.         } else {
  1012.             ret = -2;
  1013.         }
  1014.         if( 0!=ret ) {
  1015.             cout << "Failed to generate c++ header file." << endl;
  1016.             break;
  1017.         }
  1018.  
  1019.         cout << "Generate c++ source file." << endl;
  1020.         CppSourceGenerator sourceGen(&module);
  1021.         if( 0==sourceGen.Initial(argv[1]) ) {
  1022.             if( 0!=sourceGen.Generate() )
  1023.                 ret = -3;
  1024.             if( 0!=sourceGen.Finalize() )
  1025.                 ret = -3;
  1026.         } else {
  1027.             ret = -3;
  1028.         }
  1029.         if( 0!=ret ) {
  1030.             cout << "Failed to generate c++ source file." << endl;
  1031.             break;
  1032.         }
  1033.  
  1034.         cout << "Generate complete with no error." << endl;
  1035.         break;
  1036.     }
  1037.  
  1038. #if 0
  1039.     ::system("pause");
  1040. #endif
  1041.     return ret;
  1042. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top