From 2b230402818d31f124a369c8c1e69f802818b36d Mon Sep 17 00:00:00 2001 From: asfernandes Date: Tue, 7 Apr 2015 03:19:35 +0000 Subject: [PATCH] Import cloop (hash 912a16ee1424c9b8548dfdef78ad18cba901f6c8) utility. --- extern/cloop/.gitignore | 6 + extern/cloop/cloop.sln | 66 + extern/cloop/src/cloop/Expr.cpp | 119 ++ extern/cloop/src/cloop/Expr.h | 118 ++ extern/cloop/src/cloop/Generator.cpp | 1435 +++++++++++++++++ extern/cloop/src/cloop/Generator.h | 148 ++ extern/cloop/src/cloop/Lexer.cpp | 261 +++ extern/cloop/src/cloop/Lexer.h | 104 ++ extern/cloop/src/cloop/Main.cpp | 123 ++ extern/cloop/src/cloop/Parser.cpp | 418 +++++ extern/cloop/src/cloop/Parser.h | 191 +++ extern/cloop/src/cloop/cloop.vcxproj | 149 ++ extern/cloop/src/cloop/cloop.vcxproj.filters | 48 + extern/cloop/src/tests/test1/CTest.c | 418 +++++ extern/cloop/src/tests/test1/CalcCApi.c | 115 ++ extern/cloop/src/tests/test1/CalcCApi.h | 158 ++ extern/cloop/src/tests/test1/CalcCppApi.h | 777 +++++++++ .../test1/CalcPascalApi.implementation.pas | 27 + .../tests/test1/CalcPascalApi.interface.pas | 13 + .../cloop/src/tests/test1/CalcPascalApi.pas | 559 +++++++ extern/cloop/src/tests/test1/CppTest.cpp | 432 +++++ extern/cloop/src/tests/test1/Interface.idl | 69 + .../cloop/src/tests/test1/PascalClasses.pas | 247 +++ .../cloop/src/tests/test1/PascalLibrary.dpr | 40 + extern/cloop/src/tests/test1/PascalTest.dpr | 126 ++ .../cloop/src/tests/test1/test1-c-dll.vcxproj | 156 ++ .../tests/test1/test1-c-dll.vcxproj.filters | 30 + .../cloop/src/tests/test1/test1-c-exe.vcxproj | 159 ++ .../tests/test1/test1-c-exe.vcxproj.filters | 30 + .../src/tests/test1/test1-cpp-dll.vcxproj | 155 ++ .../tests/test1/test1-cpp-dll.vcxproj.filters | 27 + .../src/tests/test1/test1-cpp-exe.vcxproj | 158 ++ .../tests/test1/test1-cpp-exe.vcxproj.filters | 27 + 33 files changed, 6909 insertions(+) create mode 100644 extern/cloop/.gitignore create mode 100644 extern/cloop/cloop.sln create mode 100644 extern/cloop/src/cloop/Expr.cpp create mode 100644 extern/cloop/src/cloop/Expr.h create mode 100644 extern/cloop/src/cloop/Generator.cpp create mode 100644 extern/cloop/src/cloop/Generator.h create mode 100644 extern/cloop/src/cloop/Lexer.cpp create mode 100644 extern/cloop/src/cloop/Lexer.h create mode 100644 extern/cloop/src/cloop/Main.cpp create mode 100644 extern/cloop/src/cloop/Parser.cpp create mode 100644 extern/cloop/src/cloop/Parser.h create mode 100644 extern/cloop/src/cloop/cloop.vcxproj create mode 100644 extern/cloop/src/cloop/cloop.vcxproj.filters create mode 100644 extern/cloop/src/tests/test1/CTest.c create mode 100644 extern/cloop/src/tests/test1/CalcCApi.c create mode 100644 extern/cloop/src/tests/test1/CalcCApi.h create mode 100644 extern/cloop/src/tests/test1/CalcCppApi.h create mode 100644 extern/cloop/src/tests/test1/CalcPascalApi.implementation.pas create mode 100644 extern/cloop/src/tests/test1/CalcPascalApi.interface.pas create mode 100644 extern/cloop/src/tests/test1/CalcPascalApi.pas create mode 100644 extern/cloop/src/tests/test1/CppTest.cpp create mode 100644 extern/cloop/src/tests/test1/Interface.idl create mode 100644 extern/cloop/src/tests/test1/PascalClasses.pas create mode 100644 extern/cloop/src/tests/test1/PascalLibrary.dpr create mode 100644 extern/cloop/src/tests/test1/PascalTest.dpr create mode 100644 extern/cloop/src/tests/test1/test1-c-dll.vcxproj create mode 100644 extern/cloop/src/tests/test1/test1-c-dll.vcxproj.filters create mode 100644 extern/cloop/src/tests/test1/test1-c-exe.vcxproj create mode 100644 extern/cloop/src/tests/test1/test1-c-exe.vcxproj.filters create mode 100644 extern/cloop/src/tests/test1/test1-cpp-dll.vcxproj create mode 100644 extern/cloop/src/tests/test1/test1-cpp-dll.vcxproj.filters create mode 100644 extern/cloop/src/tests/test1/test1-cpp-exe.vcxproj create mode 100644 extern/cloop/src/tests/test1/test1-cpp-exe.vcxproj.filters diff --git a/extern/cloop/.gitignore b/extern/cloop/.gitignore new file mode 100644 index 0000000000..505798e08c --- /dev/null +++ b/extern/cloop/.gitignore @@ -0,0 +1,6 @@ +build +output +*.sdf +*.opensdf +*.suo +*.vcxproj.user diff --git a/extern/cloop/cloop.sln b/extern/cloop/cloop.sln new file mode 100644 index 0000000000..ec0ab5d655 --- /dev/null +++ b/extern/cloop/cloop.sln @@ -0,0 +1,66 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cloop", "src\cloop\cloop.vcxproj", "{7A639C01-BE0D-4BEE-D2D4-17CA5AB54E57}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test1-cpp-dll", "src\tests\test1\test1-cpp-dll.vcxproj", "{A97C1858-7DFA-8FEB-FEAE-2E9F1491692F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test1-cpp-exe", "src\tests\test1\test1-cpp-exe.vcxproj", "{096EBD8E-C0FC-4286-A01D-89D562F3AE12}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test1-c-dll", "src\tests\test1\test1-c-dll.vcxproj", "{087FC91A-451C-853D-7439-51BF770E2380}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test1-c-exe", "src\tests\test1\test1-c-exe.vcxproj", "{4495AE41-C12E-446C-AE2F-5CECF5F80B17}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7A639C01-BE0D-4BEE-D2D4-17CA5AB54E57}.Debug|Win32.ActiveCfg = Debug|Win32 + {7A639C01-BE0D-4BEE-D2D4-17CA5AB54E57}.Debug|Win32.Build.0 = Debug|Win32 + {7A639C01-BE0D-4BEE-D2D4-17CA5AB54E57}.Debug|x64.ActiveCfg = Debug|x64 + {7A639C01-BE0D-4BEE-D2D4-17CA5AB54E57}.Debug|x64.Build.0 = Debug|x64 + {7A639C01-BE0D-4BEE-D2D4-17CA5AB54E57}.Release|Win32.ActiveCfg = Release|Win32 + {7A639C01-BE0D-4BEE-D2D4-17CA5AB54E57}.Release|Win32.Build.0 = Release|Win32 + {7A639C01-BE0D-4BEE-D2D4-17CA5AB54E57}.Release|x64.ActiveCfg = Release|x64 + {7A639C01-BE0D-4BEE-D2D4-17CA5AB54E57}.Release|x64.Build.0 = Release|x64 + {A97C1858-7DFA-8FEB-FEAE-2E9F1491692F}.Debug|Win32.ActiveCfg = Debug|Win32 + {A97C1858-7DFA-8FEB-FEAE-2E9F1491692F}.Debug|Win32.Build.0 = Debug|Win32 + {A97C1858-7DFA-8FEB-FEAE-2E9F1491692F}.Debug|x64.ActiveCfg = Debug|x64 + {A97C1858-7DFA-8FEB-FEAE-2E9F1491692F}.Debug|x64.Build.0 = Debug|x64 + {A97C1858-7DFA-8FEB-FEAE-2E9F1491692F}.Release|Win32.ActiveCfg = Release|Win32 + {A97C1858-7DFA-8FEB-FEAE-2E9F1491692F}.Release|Win32.Build.0 = Release|Win32 + {A97C1858-7DFA-8FEB-FEAE-2E9F1491692F}.Release|x64.ActiveCfg = Release|x64 + {A97C1858-7DFA-8FEB-FEAE-2E9F1491692F}.Release|x64.Build.0 = Release|x64 + {096EBD8E-C0FC-4286-A01D-89D562F3AE12}.Debug|Win32.ActiveCfg = Debug|Win32 + {096EBD8E-C0FC-4286-A01D-89D562F3AE12}.Debug|Win32.Build.0 = Debug|Win32 + {096EBD8E-C0FC-4286-A01D-89D562F3AE12}.Debug|x64.ActiveCfg = Debug|x64 + {096EBD8E-C0FC-4286-A01D-89D562F3AE12}.Debug|x64.Build.0 = Debug|x64 + {096EBD8E-C0FC-4286-A01D-89D562F3AE12}.Release|Win32.ActiveCfg = Release|Win32 + {096EBD8E-C0FC-4286-A01D-89D562F3AE12}.Release|Win32.Build.0 = Release|Win32 + {096EBD8E-C0FC-4286-A01D-89D562F3AE12}.Release|x64.ActiveCfg = Release|x64 + {096EBD8E-C0FC-4286-A01D-89D562F3AE12}.Release|x64.Build.0 = Release|x64 + {087FC91A-451C-853D-7439-51BF770E2380}.Debug|Win32.ActiveCfg = Debug|Win32 + {087FC91A-451C-853D-7439-51BF770E2380}.Debug|Win32.Build.0 = Debug|Win32 + {087FC91A-451C-853D-7439-51BF770E2380}.Debug|x64.ActiveCfg = Debug|x64 + {087FC91A-451C-853D-7439-51BF770E2380}.Debug|x64.Build.0 = Debug|x64 + {087FC91A-451C-853D-7439-51BF770E2380}.Release|Win32.ActiveCfg = Release|Win32 + {087FC91A-451C-853D-7439-51BF770E2380}.Release|Win32.Build.0 = Release|Win32 + {087FC91A-451C-853D-7439-51BF770E2380}.Release|x64.ActiveCfg = Release|x64 + {087FC91A-451C-853D-7439-51BF770E2380}.Release|x64.Build.0 = Release|x64 + {4495AE41-C12E-446C-AE2F-5CECF5F80B17}.Debug|Win32.ActiveCfg = Debug|Win32 + {4495AE41-C12E-446C-AE2F-5CECF5F80B17}.Debug|Win32.Build.0 = Debug|Win32 + {4495AE41-C12E-446C-AE2F-5CECF5F80B17}.Debug|x64.ActiveCfg = Debug|x64 + {4495AE41-C12E-446C-AE2F-5CECF5F80B17}.Debug|x64.Build.0 = Debug|x64 + {4495AE41-C12E-446C-AE2F-5CECF5F80B17}.Release|Win32.ActiveCfg = Release|Win32 + {4495AE41-C12E-446C-AE2F-5CECF5F80B17}.Release|Win32.Build.0 = Release|Win32 + {4495AE41-C12E-446C-AE2F-5CECF5F80B17}.Release|x64.ActiveCfg = Release|x64 + {4495AE41-C12E-446C-AE2F-5CECF5F80B17}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/extern/cloop/src/cloop/Expr.cpp b/extern/cloop/src/cloop/Expr.cpp new file mode 100644 index 0000000000..4698b6d316 --- /dev/null +++ b/extern/cloop/src/cloop/Expr.cpp @@ -0,0 +1,119 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Adriano dos Santos Fernandes. + * + * Copyright (c) 2014 Adriano dos Santos Fernandes + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + */ + +#include "Expr.h" +#include "Parser.h" +#include + +using std::string; + + +//-------------------------------------- + + +IntLiteralExpr::IntLiteralExpr(int value) + : value(value) +{ +} + +string IntLiteralExpr::generate(Language language, const string& prefix) +{ + char buffer[64]; + sprintf(buffer, "%d", value); + return buffer; +} + + +//-------------------------------------- + + +BooleanLiteralExpr::BooleanLiteralExpr(bool value) + : value(value) +{ +} + +string BooleanLiteralExpr::generate(Language language, const string& prefix) +{ + return value ? "true" : "false"; +} + + +//-------------------------------------- + + +NegateExpr::NegateExpr(Expr* expr) + : expr(expr) +{ +} + +std::string NegateExpr::generate(Language language, const string& prefix) +{ + return "-" + expr->generate(language, prefix); +} + + +//-------------------------------------- + + +ConstantExpr::ConstantExpr(Interface* interface, string name) + : interface(interface), + name(name) +{ +} + +string ConstantExpr::generate(Language language, const string& prefix) +{ + string retPrefix; + + switch (language) + { + case LANGUAGE_C: + retPrefix = prefix + interface->name + "_"; + break; + + case LANGUAGE_CPP: + retPrefix = prefix + interface->name + "::"; + break; + + case LANGUAGE_PASCAL: + retPrefix = prefix + interface->name + "."; + break; + } + + return retPrefix + name; +} + + +//-------------------------------------- + + +BitwiseOrExpr::BitwiseOrExpr(Expr* expr1, Expr* expr2) + : expr1(expr1), + expr2(expr2) +{ +} + +string BitwiseOrExpr::generate(Language language, const string& prefix) +{ + return expr1->generate(language, prefix) + + (language == LANGUAGE_PASCAL ? " or " : " | ") + + expr2->generate(language, prefix); +} diff --git a/extern/cloop/src/cloop/Expr.h b/extern/cloop/src/cloop/Expr.h new file mode 100644 index 0000000000..ec7a3e95de --- /dev/null +++ b/extern/cloop/src/cloop/Expr.h @@ -0,0 +1,118 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Adriano dos Santos Fernandes. + * + * Copyright (c) 2014 Adriano dos Santos Fernandes + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + */ + +#ifndef CLOOP_EXPR_H +#define CLOOP_EXPR_H + +#include + + +class Interface; + + +enum Language +{ + LANGUAGE_C, + LANGUAGE_CPP, + LANGUAGE_PASCAL +}; + + +class Expr +{ +public: + virtual ~Expr() + { + } + +public: + virtual std::string generate(Language language, const std::string& prefix) = 0; +}; + + +class IntLiteralExpr : public Expr +{ +public: + IntLiteralExpr(int value); + +public: + virtual std::string generate(Language language, const std::string& prefix); + +private: + int value; +}; + + +class BooleanLiteralExpr : public Expr +{ +public: + BooleanLiteralExpr(bool value); + +public: + virtual std::string generate(Language language, const std::string& prefix); + +private: + bool value; +}; + + +class NegateExpr : public Expr +{ +public: + NegateExpr(Expr* expr); + +public: + virtual std::string generate(Language language, const std::string& prefix); + +private: + Expr* expr; +}; + + +class ConstantExpr : public Expr +{ +public: + ConstantExpr(Interface* interface, std::string name); + +public: + virtual std::string generate(Language language, const std::string& prefix); + +private: + Interface* interface; + std::string name; +}; + + +class BitwiseOrExpr : public Expr +{ +public: + BitwiseOrExpr(Expr* expr1, Expr* expr2); + +public: + virtual std::string generate(Language language, const std::string& prefix); + +private: + Expr* expr1; + Expr* expr2; +}; + + +#endif // CLOOP_EXPR_H diff --git a/extern/cloop/src/cloop/Generator.cpp b/extern/cloop/src/cloop/Generator.cpp new file mode 100644 index 0000000000..2d883c0cf9 --- /dev/null +++ b/extern/cloop/src/cloop/Generator.cpp @@ -0,0 +1,1435 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Adriano dos Santos Fernandes. + * + * Copyright (c) 2014 Adriano dos Santos Fernandes + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + */ + +#include "Generator.h" +#include "Expr.h" +#include +#include +#include +#include +#include +#include + +using std::deque; +using std::runtime_error; +using std::set; +using std::string; +using std::vector; + + +//-------------------------------------- + + +const char* const Generator::AUTOGEN_MSG = + "This file was autogenerated by cloop - Cross Language Object Oriented Programming"; + + +//-------------------------------------- + + +FileGenerator::FileGenerator(const string& filename, const string& prefix) + : prefix(prefix) +{ + out = fopen(filename.c_str(), "w+"); +} + +FileGenerator::~FileGenerator() +{ + fclose(out); +} + + +//-------------------------------------- + + +CBasedGenerator::CBasedGenerator(const string& filename, const string& prefix, bool cPlusPlus) + : FileGenerator(filename, prefix), + cPlusPlus(cPlusPlus) +{ +} + +string CBasedGenerator::convertType(const TypeRef& typeRef) +{ + string ret(typeRef.isConst ? "const " : ""); + + switch (typeRef.token.type) + { + case Token::TYPE_BOOLEAN: + ret += "FB_BOOLEAN"; // seems to be more portable than bool, specially thinking on pointers + break; + + case Token::TYPE_INT: + ret += "int"; + break; + + case Token::TYPE_INT64: + ret += "ISC_INT64"; //int64_t + break; + + case Token::TYPE_INTPTR: + ret += "intptr_t"; + break; + + case Token::TYPE_STRING: + ret += "char*"; + break; + + case Token::TYPE_UCHAR: + ret += "unsigned char"; + break; + + case Token::TYPE_UINT: + ret += "unsigned"; + break; + + case Token::TYPE_UINT64: + ret += "ISC_UINT64"; //uint64_t + break; + + case Token::TYPE_IDENTIFIER: + ret += string(cPlusPlus || typeRef.type == BaseType::TYPE_TYPEDEF ? "" : "struct ") + + (typeRef.type == BaseType::TYPE_INTERFACE ? prefix : "") + typeRef.token.text; + + if (typeRef.type == BaseType::TYPE_INTERFACE) + ret += "*"; + break; + + default: + ret += typeRef.token.text; + break; + } + + if (typeRef.isPointer) + ret += "*"; + + return ret; +} + + +//-------------------------------------- + + +CppGenerator::CppGenerator(const string& filename, const string& prefix, Parser* parser, + const string& headerGuard, const string& nameSpace) + : CBasedGenerator(filename, prefix, true), + parser(parser), + headerGuard(headerGuard), + nameSpace(nameSpace) +{ +} + +void CppGenerator::generate() +{ + fprintf(out, "// %s\n\n", AUTOGEN_MSG); + + fprintf(out, "#ifndef %s\n", headerGuard.c_str()); + fprintf(out, "#define %s\n\n", headerGuard.c_str()); + ///fprintf(out, "#include \n\n"); + + fprintf(out, "#ifndef CLOOP_CARG\n"); + fprintf(out, "#define CLOOP_CARG\n"); + fprintf(out, "#endif\n\n\n"); + + fprintf(out, "namespace %s\n", nameSpace.c_str()); + fprintf(out, "{\n"); + fprintf(out, "\tclass DoNotInherit\n"); + fprintf(out, "\t{\n"); + fprintf(out, "\t};\n"); + fprintf(out, "\n"); + fprintf(out, "\ttemplate \n"); + fprintf(out, "\tclass Inherit : public T\n"); + fprintf(out, "\t{\n"); + fprintf(out, "\tpublic:\n"); + fprintf(out, "\t\tInherit(DoNotInherit = DoNotInherit())\n"); + fprintf(out, "\t\t\t: T(DoNotInherit())\n"); + fprintf(out, "\t\t{\n"); + fprintf(out, "\t\t}\n"); + fprintf(out, "\t};\n"); + fprintf(out, "\n"); + + fprintf(out, "\t// Forward interfaces declarations\n\n"); + + for (vector::iterator i = parser->interfaces.begin(); + i != parser->interfaces.end(); + ++i) + { + Interface* interface = *i; + + fprintf(out, "\tclass %s%s;\n", prefix.c_str(), interface->name.c_str()); + } + + fprintf(out, "\n"); + fprintf(out, "\t// Interfaces declarations\n\n"); + + for (vector::iterator i = parser->interfaces.begin(); + i != parser->interfaces.end(); + ++i) + { + Interface* interface = *i; + + deque methods; + + for (Interface* p = interface; p; p = p->super) + methods.insert(methods.begin(), p->methods.begin(), p->methods.end()); + + if (!interface->super) + fprintf(out, "\tclass %s%s\n", prefix.c_str(), interface->name.c_str()); + else + { + fprintf(out, "\tclass %s%s : public %s%s\n", + prefix.c_str(), interface->name.c_str(), + prefix.c_str(), interface->super->name.c_str()); + } + + fprintf(out, "\t{\n"); + fprintf(out, "\tpublic:\n"); + + if (!interface->super) + { + fprintf(out, "\t\tstruct VTable\n"); + fprintf(out, "\t\t{\n"); + fprintf(out, "\t\t\tvoid* cloopDummy[%d];\n", DUMMY_VTABLE); + fprintf(out, "\t\t\tuintptr_t version;\n"); + } + else + { + fprintf(out, "\t\tstruct VTable : public %s%s::VTable\n", + prefix.c_str(), interface->super->name.c_str()); + fprintf(out, "\t\t{\n"); + } + + for (vector::iterator j = interface->methods.begin(); + j != interface->methods.end(); + ++j) + { + Method* method = *j; + + fprintf(out, "\t\t\t%s (CLOOP_CARG *%s)(%s%s%s* self", + convertType(method->returnTypeRef).c_str(), + method->name.c_str(), + (method->isConst ? "const " : ""), + prefix.c_str(), + interface->name.c_str()); + + for (vector::iterator k = method->parameters.begin(); + k != method->parameters.end(); + ++k) + { + Parameter* parameter = *k; + + fprintf(out, ", %s %s", + convertType(parameter->typeRef).c_str(), parameter->name.c_str()); + } + + fprintf(out, ") throw();\n"); + } + + fprintf(out, "\t\t};\n"); + fprintf(out, "\n"); + + if (!interface->super) + { + fprintf(out, "\t\tvoid* cloopDummy[%d];\n", DUMMY_INSTANCE); + fprintf(out, "\t\tVTable* cloopVTable;\n"); + fprintf(out, "\n"); + } + + fprintf(out, "\tprotected:\n"); + fprintf(out, "\t\t%s%s(DoNotInherit)\n", prefix.c_str(), interface->name.c_str()); + + if (interface->super) + { + fprintf(out, "\t\t\t: %s%s(DoNotInherit())\n", + prefix.c_str(), interface->super->name.c_str()); + } + + fprintf(out, "\t\t{\n"); + fprintf(out, "\t\t}\n"); + fprintf(out, "\n"); + fprintf(out, "\t\t~%s%s()\n", prefix.c_str(), interface->name.c_str()); + fprintf(out, "\t\t{\n"); + fprintf(out, "\t\t}\n"); + fprintf(out, "\n"); + + fprintf(out, "\tpublic:\n"); + fprintf(out, "\t\tstatic const unsigned VERSION = %u;\n", interface->version); + + if (!interface->constants.empty()) + fprintf(out, "\n"); + + for (vector::iterator j = interface->constants.begin(); + j != interface->constants.end(); + ++j) + { + Constant* constant = *j; + + fprintf(out, "\t\tstatic const %s %s = %s;\n", + convertType(constant->typeRef).c_str(), + constant->name.c_str(), + constant->expr->generate(LANGUAGE_CPP, prefix).c_str()); + } + + for (vector::iterator j = interface->methods.begin(); + j != interface->methods.end(); + ++j) + { + Method* method = *j; + + fprintf(out, "\n\t\t"); + + string statusName; + + if (!method->parameters.empty() && + parser->exceptionInterface && + method->parameters.front()->typeRef.token.text == parser->exceptionInterface->name) + { + statusName = method->parameters.front()->name; + fprintf(out, "template "); + } + + fprintf(out, "%s %s(", + convertType(method->returnTypeRef).c_str(), method->name.c_str()); + + for (vector::iterator k = method->parameters.begin(); + k != method->parameters.end(); + ++k) + { + Parameter* parameter = *k; + + if (k != method->parameters.begin()) + fprintf(out, ", "); + + if (k == method->parameters.begin() && !statusName.empty()) + fprintf(out, "StatusType* %s", parameter->name.c_str()); + else + { + fprintf(out, "%s %s", + convertType(parameter->typeRef).c_str(), parameter->name.c_str()); + } + } + + fprintf(out, ")%s\n", (method->isConst ? " const" : "")); + fprintf(out, "\t\t{\n"); + + if (method->version - (interface->super ? interface->super->version : 0) != 1) + { + fprintf(out, "\t\t\tif (cloopVTable->version < %d)\n", method->version); + fprintf(out, "\t\t\t{\n"); + + if (!statusName.empty()) + { + fprintf(out, + "\t\t\t\tStatusType::setVersionError(%s, \"%s%s\", cloopVTable->version, %d);\n", + statusName.c_str(), + prefix.c_str(), + interface->name.c_str(), + method->version); + + fprintf(out, "\t\t\t\tStatusType::checkException(%s);\n", statusName.c_str()); + } + + fprintf(out, "\t\t\t\treturn"); + + if (method->returnTypeRef.token.type != Token::TYPE_VOID || + method->returnTypeRef.isPointer) + { + fprintf(out, " %s", + (method->notImplementedExpr ? + method->notImplementedExpr->generate(LANGUAGE_CPP, prefix).c_str() : + "0")); + } + + fprintf(out, ";\n"); + fprintf(out, "\t\t\t}\n"); + } + + if (!statusName.empty()) + { + fprintf(out, "\t\t\t"); + + fprintf(out, "StatusType::clearException(%s)", statusName.c_str()); + + fprintf(out, ";\n"); + } + + fprintf(out, "\t\t\t"); + + if (method->returnTypeRef.token.type != Token::TYPE_VOID || + method->returnTypeRef.isPointer) + { + fprintf(out, "%s ret = ", convertType(method->returnTypeRef).c_str()); + } + + fprintf(out, "static_cast(this->cloopVTable)->%s(this", + method->name.c_str()); + + for (vector::iterator k = method->parameters.begin(); + k != method->parameters.end(); + ++k) + { + Parameter* parameter = *k; + fprintf(out, ", %s", parameter->name.c_str()); + } + + fprintf(out, ")"); + fprintf(out, ";\n"); + + if (!method->parameters.empty() && + parser->exceptionInterface && + method->parameters.front()->typeRef.token.text == parser->exceptionInterface->name) + { + fprintf(out, "\t\t\tStatusType::checkException(%s);\n", + method->parameters.front()->name.c_str()); + } + + if (method->returnTypeRef.token.type != Token::TYPE_VOID || + method->returnTypeRef.isPointer) + { + fprintf(out, "\t\t\treturn ret;\n"); + } + + fprintf(out, "\t\t}\n"); + } + + fprintf(out, "\t};\n\n"); + } + + fprintf(out, "\t// Interfaces implementations\n"); + + for (vector::iterator i = parser->interfaces.begin(); + i != parser->interfaces.end(); + ++i) + { + Interface* interface = *i; + + deque methods; + + for (Interface* p = interface; p; p = p->super) + methods.insert(methods.begin(), p->methods.begin(), p->methods.end()); + + fprintf(out, "\n"); + fprintf(out, "\ttemplate \n"); + fprintf(out, "\tclass %s%sBaseImpl : public Base\n", + prefix.c_str(), interface->name.c_str()); + fprintf(out, "\t{\n"); + fprintf(out, "\tpublic:\n"); + fprintf(out, "\t\ttypedef %s%s Declaration;\n", prefix.c_str(), interface->name.c_str()); + fprintf(out, "\n"); + fprintf(out, "\t\t%s%sBaseImpl(DoNotInherit = DoNotInherit())\n", + prefix.c_str(), interface->name.c_str()); + fprintf(out, "\t\t{\n"); + fprintf(out, "\t\t\tstatic struct VTableImpl : Base::VTable\n"); + fprintf(out, "\t\t\t{\n"); + fprintf(out, "\t\t\t\tVTableImpl()\n"); + fprintf(out, "\t\t\t\t{\n"); + fprintf(out, "\t\t\t\t\tthis->version = Base::VERSION;\n"); + + for (deque::iterator j = methods.begin(); j != methods.end(); ++j) + { + Method* method = *j; + + fprintf(out, "\t\t\t\t\tthis->%s = &Name::cloop%sDispatcher;\n", + method->name.c_str(), method->name.c_str()); + } + + fprintf(out, "\t\t\t\t}\n"); + fprintf(out, "\t\t\t} vTable;\n"); + fprintf(out, "\n"); + + fprintf(out, "\t\t\tthis->cloopVTable = &vTable;\n"); + fprintf(out, "\t\t}\n"); + + // We generate all bases dispatchers so indirect overrides work. At the same time, we + // inherit from all bases impls, so pure virtual methods are introduced and required to + // be overriden in the user's implementation. + + for (Interface* p = interface; p; p = p->super) + { + for (vector::iterator j = p->methods.begin(); j != p->methods.end(); ++j) + { + Method* method = *j; + + fprintf(out, "\n"); + fprintf(out, "\t\tstatic %s CLOOP_CARG cloop%sDispatcher(%s%s%s* self", + convertType(method->returnTypeRef).c_str(), + method->name.c_str(), + (method->isConst ? "const " : ""), + prefix.c_str(), + p->name.c_str()); + + for (vector::iterator k = method->parameters.begin(); + k != method->parameters.end(); + ++k) + { + Parameter* parameter = *k; + + fprintf(out, ", %s %s", + convertType(parameter->typeRef).c_str(), parameter->name.c_str()); + } + + Parameter* exceptionParameter = + (!method->parameters.empty() && + parser->exceptionInterface && + method->parameters.front()->typeRef.token.text == parser->exceptionInterface->name + ) ? method->parameters.front() : NULL; + + fprintf(out, ") throw()\n"); + fprintf(out, "\t\t{\n"); + + if (exceptionParameter) + { + fprintf(out, "\t\t\tStatusType %s2(%s);\n", + exceptionParameter->name.c_str(), + exceptionParameter->name.c_str()); + fprintf(out, "\n"); + } + + fprintf(out, "\t\t\ttry\n"); + fprintf(out, "\t\t\t{\n"); + + fprintf(out, "\t\t\t\t"); + + if (method->returnTypeRef.token.type != Token::TYPE_VOID || + method->returnTypeRef.isPointer) + { + fprintf(out, "return "); + } + + fprintf(out, "static_cast<%sName*>(self)->Name::%s(", + (method->isConst ? "const " : ""), + method->name.c_str()); + + for (vector::iterator k = method->parameters.begin(); + k != method->parameters.end(); + ++k) + { + Parameter* parameter = *k; + + if (k != method->parameters.begin()) + fprintf(out, ", "); + + if (parameter == exceptionParameter) + fprintf(out, "&%s2", parameter->name.c_str()); + else + fprintf(out, "%s", parameter->name.c_str()); + } + + fprintf(out, ");\n"); + + fprintf(out, "\t\t\t}\n"); + fprintf(out, "\t\t\tcatch (...)\n"); + fprintf(out, "\t\t\t{\n"); + fprintf(out, "\t\t\t\tStatusType::catchException(%s);\n", + (exceptionParameter ? ("&" + exceptionParameter->name + "2").c_str() : "0")); + + if (method->returnTypeRef.token.type != Token::TYPE_VOID || + method->returnTypeRef.isPointer) + { + fprintf(out, "\t\t\t\treturn static_cast<%s>(0);\n", + convertType(method->returnTypeRef).c_str()); + } + + fprintf(out, "\t\t\t}\n"); + + fprintf(out, "\t\t}\n"); + } + } + + fprintf(out, "\t};\n\n"); + + if (!interface->super) + { + fprintf(out, "\ttemplate >\n", + prefix.c_str(), interface->name.c_str()); + } + else + { + string base; + unsigned baseCount = 0; + + for (Interface* p = interface->super; p; p = p->super) + { + base += prefix + p->name + "Implname; + + while (baseCount-- > 0) + base += "> > "; + + fprintf(out, "\ttemplate \n", base.c_str()); + } + + fprintf(out, "\tclass %s%sImpl : public %s%sBaseImpl\n", + prefix.c_str(), interface->name.c_str(), prefix.c_str(), interface->name.c_str()); + fprintf(out, "\t{\n"); + fprintf(out, "\tprotected:\n"); + fprintf(out, "\t\t%s%sImpl(DoNotInherit = DoNotInherit())\n", + prefix.c_str(), interface->name.c_str()); + fprintf(out, "\t\t{\n"); + fprintf(out, "\t\t}\n"); + fprintf(out, "\n"); + fprintf(out, "\tpublic:\n"); + fprintf(out, "\t\tvirtual ~%s%sImpl()\n", prefix.c_str(), interface->name.c_str()); + fprintf(out, "\t\t{\n"); + fprintf(out, "\t\t}\n"); + fprintf(out, "\n"); + + for (vector::iterator j = interface->methods.begin(); + j != interface->methods.end(); + ++j) + { + Method* method = *j; + + Parameter* exceptionParameter = + (!method->parameters.empty() && + parser->exceptionInterface && + method->parameters.front()->typeRef.token.text == parser->exceptionInterface->name + ) ? method->parameters.front() : NULL; + + fprintf(out, "\t\tvirtual %s %s(", + convertType(method->returnTypeRef).c_str(), method->name.c_str()); + + for (vector::iterator k = method->parameters.begin(); + k != method->parameters.end(); + ++k) + { + Parameter* parameter = *k; + + if (k != method->parameters.begin()) + fprintf(out, ", "); + + if (parameter == exceptionParameter) + fprintf(out, "StatusType* %s", parameter->name.c_str()); + else + { + fprintf(out, "%s %s", + convertType(parameter->typeRef).c_str(), parameter->name.c_str()); + } + } + + fprintf(out, ")%s = 0;\n", (method->isConst ? " const" : "")); + } + + fprintf(out, "\t};\n"); + } + + fprintf(out, "};\n\n"); + fprintf(out, "\n"); + + fprintf(out, "#endif\t// %s\n", headerGuard.c_str()); +} + + +//-------------------------------------- + + +CHeaderGenerator::CHeaderGenerator(const string& filename, const string& prefix, Parser* parser, + const string& headerGuard) + : CBasedGenerator(filename, prefix, false), + parser(parser), + headerGuard(headerGuard) +{ +} + +void CHeaderGenerator::generate() +{ + fprintf(out, "/* %s */\n\n", AUTOGEN_MSG); + + fprintf(out, "#ifndef %s\n", headerGuard.c_str()); + fprintf(out, "#define %s\n\n", headerGuard.c_str()); + fprintf(out, "#include \n\n"); + + fprintf(out, "#ifndef CLOOP_EXTERN_C\n"); + fprintf(out, "#ifdef __cplusplus\n"); + fprintf(out, "#define CLOOP_EXTERN_C extern \"C\"\n"); + fprintf(out, "#else\n"); + fprintf(out, "#define CLOOP_EXTERN_C\n"); + fprintf(out, "#endif\n"); + fprintf(out, "#endif\n\n\n"); + + for (vector::iterator i = parser->interfaces.begin(); + i != parser->interfaces.end(); + ++i) + { + Interface* interface = *i; + + fprintf(out, "struct %s%s;\n", prefix.c_str(), interface->name.c_str()); + } + + fprintf(out, "\n\n"); + + for (vector::iterator i = parser->interfaces.begin(); + i != parser->interfaces.end(); + ++i) + { + Interface* interface = *i; + + deque methods; + + for (Interface* p = interface; p; p = p->super) + methods.insert(methods.begin(), p->methods.begin(), p->methods.end()); + + fprintf(out, "#define %s%s_VERSION %d\n\n", + prefix.c_str(), interface->name.c_str(), (int) methods.size()); + + for (vector::iterator j = interface->constants.begin(); + j != interface->constants.end(); + ++j) + { + Constant* constant = *j; + + fprintf(out, "#define %s%s_%s ((%s) (%s))\n", + prefix.c_str(), + interface->name.c_str(), + constant->name.c_str(), + convertType(constant->typeRef).c_str(), + constant->expr->generate(LANGUAGE_C, prefix).c_str()); + } + + if (!interface->constants.empty()) + fprintf(out, "\n"); + + fprintf(out, "struct %s%s;\n\n", prefix.c_str(), interface->name.c_str()); + + fprintf(out, "struct %s%sVTable\n", prefix.c_str(), interface->name.c_str()); + fprintf(out, "{\n"); + fprintf(out, "\tvoid* cloopDummy[%d];\n", DUMMY_VTABLE); + fprintf(out, "\tuintptr_t version;\n"); + + for (deque::iterator j = methods.begin(); j != methods.end(); ++j) + { + Method* method = *j; + + fprintf(out, "\t%s (*%s)(%sstruct %s%s* self", + convertType(method->returnTypeRef).c_str(), + method->name.c_str(), + (method->isConst ? "const " : ""), + prefix.c_str(), + interface->name.c_str()); + + for (vector::iterator k = method->parameters.begin(); + k != method->parameters.end(); + ++k) + { + Parameter* parameter = *k; + + fprintf(out, ", %s %s", convertType(parameter->typeRef).c_str(), + parameter->name.c_str()); + } + + fprintf(out, ");\n"); + } + + fprintf(out, "};\n\n"); + + fprintf(out, "struct %s%s\n", prefix.c_str(), interface->name.c_str()); + fprintf(out, "{\n"); + fprintf(out, "\tvoid* cloopDummy[%d];\n", DUMMY_INSTANCE); + fprintf(out, "\tstruct %s%sVTable* vtable;\n", prefix.c_str(), interface->name.c_str()); + fprintf(out, "};\n\n"); + + for (deque::iterator j = methods.begin(); j != methods.end(); ++j) + { + Method* method = *j; + + fprintf(out, "CLOOP_EXTERN_C %s %s%s_%s(%sstruct %s%s* self", + convertType(method->returnTypeRef).c_str(), + prefix.c_str(), + interface->name.c_str(), + method->name.c_str(), + (method->isConst ? "const " : ""), + prefix.c_str(), + interface->name.c_str()); + + for (vector::iterator k = method->parameters.begin(); + k != method->parameters.end(); + ++k) + { + Parameter* parameter = *k; + + fprintf(out, ", %s %s", + convertType(parameter->typeRef).c_str(), parameter->name.c_str()); + } + + fprintf(out, ");\n"); + } + + fprintf(out, "\n"); + } + + fprintf(out, "\n"); + fprintf(out, "#endif\t// %s\n", headerGuard.c_str()); +} + + +//-------------------------------------- + + +CImplGenerator::CImplGenerator(const string& filename, const string& prefix, Parser* parser, + const string& includeFilename) + : CBasedGenerator(filename, prefix, false), + parser(parser), + includeFilename(includeFilename) +{ +} + +void CImplGenerator::generate() +{ + fprintf(out, "/* %s */\n\n", AUTOGEN_MSG); + + fprintf(out, "#include \"%s\"\n\n\n", includeFilename.c_str()); + + for (vector::iterator i = parser->interfaces.begin(); + i != parser->interfaces.end(); + ++i) + { + Interface* interface = *i; + + deque methods; + + for (Interface* p = interface; p; p = p->super) + methods.insert(methods.begin(), p->methods.begin(), p->methods.end()); + + for (deque::iterator j = methods.begin(); j != methods.end(); ++j) + { + Method* method = *j; + + fprintf(out, "CLOOP_EXTERN_C %s %s%s_%s(%sstruct %s%s* self", + convertType(method->returnTypeRef).c_str(), + prefix.c_str(), + interface->name.c_str(), + method->name.c_str(), + (method->isConst ? "const " : ""), + prefix.c_str(), + interface->name.c_str()); + + for (vector::iterator k = method->parameters.begin(); + k != method->parameters.end(); + ++k) + { + Parameter* parameter = *k; + + fprintf(out, ", %s %s", + convertType(parameter->typeRef).c_str(), parameter->name.c_str()); + } + + fprintf(out, ")\n"); + fprintf(out, "{\n"); + fprintf(out, "\t"); + + //// TODO: checkVersion + + if (method->returnTypeRef.token.type != Token::TYPE_VOID || + method->returnTypeRef.isPointer) + { + fprintf(out, "return "); + } + + fprintf(out, "self->vtable->%s(self", method->name.c_str()); + + for (vector::iterator k = method->parameters.begin(); + k != method->parameters.end(); + ++k) + { + Parameter* parameter = *k; + fprintf(out, ", %s", parameter->name.c_str()); + } + + fprintf(out, ");\n"); + fprintf(out, "}\n\n"); + } + } +} + + +//-------------------------------------- + + +PascalGenerator::PascalGenerator(const string& filename, const string& prefix, Parser* parser, + const string& unitName, const std::string& additionalUses, const std::string& interfaceFile, + const std::string& implementationFile, const std::string& exceptionClass) + : FileGenerator(filename, prefix), + parser(parser), + unitName(unitName), + additionalUses(additionalUses), + interfaceFile(interfaceFile), + implementationFile(implementationFile), + exceptionClass(exceptionClass) +{ +} + +void PascalGenerator::generate() +{ + fprintf(out, "{ %s }\n\n", AUTOGEN_MSG); + + fprintf(out, "unit %s;\n\n", unitName.c_str()); + fprintf(out, "interface\n\n"); + fprintf(out, "uses Classes"); + + if (!additionalUses.empty()) + fprintf(out, ", %s", additionalUses.c_str()); + + fprintf(out, ";\n\n"); + + fprintf(out, "type\n"); + fprintf(out, "{$IFNDEF FPC}\n"); + fprintf(out, "\tQWord = UInt64;\n"); + fprintf(out, "{$ENDIF}\n\n"); + + for (vector::iterator i = parser->interfaces.begin(); + i != parser->interfaces.end(); + ++i) + { + Interface* interface = *i; + fprintf(out, "\t%s = class;\n", escapeName(interface->name).c_str()); + } + + fprintf(out, "\n"); + + insertFile(interfaceFile); + + // Pass at every type to fill pointerTypes. We need it in advance. + + for (vector::iterator i = parser->interfaces.begin(); + i != parser->interfaces.end(); + ++i) + { + Interface* interface = *i; + + for (vector::iterator j = interface->methods.begin(); + j != interface->methods.end(); + ++j) + { + Method* method = *j; + + convertType(method->returnTypeRef); + + for (vector::iterator k = method->parameters.begin(); + k != method->parameters.end(); + ++k) + { + Parameter* parameter = *k; + convertParameter(*parameter); + } + } + } + + for (set::iterator i = pointerTypes.begin(); i != pointerTypes.end(); ++i) + { + string type = *i; + fprintf(out, "\t%sPtr = ^%s;\n", type.c_str(), type.c_str()); + } + + if (!pointerTypes.empty()) + fprintf(out, "\n"); + + for (vector::iterator i = parser->interfaces.begin(); + i != parser->interfaces.end(); + ++i) + { + Interface* interface = *i; + + for (vector::iterator j = interface->methods.begin(); + j != interface->methods.end(); + ++j) + { + Method* method = *j; + + bool isProcedure = method->returnTypeRef.token.type == Token::TYPE_VOID && + !method->returnTypeRef.isPointer; + + fprintf(out, "\t%s_%sPtr = %s(this: %s", + escapeName(interface->name).c_str(), escapeName(method->name).c_str(), + (isProcedure ? "procedure" : "function"), + escapeName(interface->name).c_str()); + + for (vector::iterator k = method->parameters.begin(); + k != method->parameters.end(); + ++k) + { + Parameter* parameter = *k; + fprintf(out, "; %s", convertParameter(*parameter).c_str()); + } + + fprintf(out, ")"); + + if (!isProcedure) + fprintf(out, ": %s", convertType(method->returnTypeRef).c_str()); + + fprintf(out, "; cdecl;\n"); + } + } + + fprintf(out, "\n"); + + for (vector::iterator i = parser->interfaces.begin(); + i != parser->interfaces.end(); + ++i) + { + Interface* interface = *i; + + fprintf(out, "\t%sVTable = class", escapeName(interface->name).c_str()); + + if (interface->super) + fprintf(out, "(%sVTable)", interface->super->name.c_str()); + + fprintf(out, "\n"); + + if (!interface->super) + fprintf(out, "\t\tversion: NativeInt;\n"); + + for (vector::iterator j = interface->methods.begin(); + j != interface->methods.end(); + ++j) + { + Method* method = *j; + + fprintf(out, "\t\t%s: %s_%sPtr;\n", escapeName(method->name).c_str(), + escapeName(interface->name).c_str(), escapeName(method->name).c_str()); + } + + fprintf(out, "\tend;\n\n"); + + fprintf(out, "\t%s = class", escapeName(interface->name).c_str()); + + if (interface->super) + fprintf(out, "(%s)", interface->super->name.c_str()); + + fprintf(out, "\n"); + + if (!interface->super) + fprintf(out, "\t\tvTable: %sVTable;\n\n", escapeName(interface->name).c_str()); + + unsigned version = 0; + + for (Interface* p = interface; p; p = p->super) + version += p->methods.size(); + + fprintf(out, "\t\tconst VERSION = %d;\n", version); + + for (vector::iterator j = interface->constants.begin(); + j != interface->constants.end(); + ++j) + { + Constant* constant = *j; + + fprintf(out, "\t\tconst %s = %s(%s);\n", + constant->name.c_str(), + convertType(constant->typeRef).c_str(), + constant->expr->generate(LANGUAGE_PASCAL, prefix).c_str()); + } + + fprintf(out, "\n"); + + for (vector::iterator j = interface->methods.begin(); + j != interface->methods.end(); + ++j) + { + Method* method = *j; + + bool isProcedure = method->returnTypeRef.token.type == Token::TYPE_VOID && + !method->returnTypeRef.isPointer; + + fprintf(out, "\t\t%s %s(", + (isProcedure ? "procedure" : "function"), + escapeName(method->name).c_str()); + + for (vector::iterator k = method->parameters.begin(); + k != method->parameters.end(); + ++k) + { + Parameter* parameter = *k; + + if (k != method->parameters.begin()) + fprintf(out, "; "); + + fprintf(out, "%s", convertParameter(*parameter).c_str()); + } + + fprintf(out, ")"); + + if (!isProcedure) + fprintf(out, ": %s", convertType(method->returnTypeRef).c_str()); + + fprintf(out, ";\n"); + } + + fprintf(out, "\tend;\n\n"); + + fprintf(out, "\t%sImpl = class(%s)\n", + escapeName(interface->name).c_str(), escapeName(interface->name).c_str()); + fprintf(out, "\t\tconstructor create;\n\n"); + + deque methods; + + for (Interface* p = interface; p; p = p->super) + methods.insert(methods.begin(), p->methods.begin(), p->methods.end()); + + for (deque::iterator j = methods.begin(); j != methods.end(); ++j) + { + Method* method = *j; + + bool isProcedure = method->returnTypeRef.token.type == Token::TYPE_VOID && + !method->returnTypeRef.isPointer; + + fprintf(out, "\t\t%s %s(", + (isProcedure ? "procedure" : "function"), + escapeName(method->name).c_str()); + + for (vector::iterator k = method->parameters.begin(); + k != method->parameters.end(); + ++k) + { + Parameter* parameter = *k; + + if (k != method->parameters.begin()) + fprintf(out, "; "); + + fprintf(out, "%s", convertParameter(*parameter).c_str()); + } + + fprintf(out, ")"); + + if (!isProcedure) + fprintf(out, ": %s", convertType(method->returnTypeRef).c_str()); + + fprintf(out, "; virtual; abstract;\n"); + } + + fprintf(out, "\tend;\n\n"); + } + + fprintf(out, "implementation\n\n"); + + for (vector::iterator i = parser->interfaces.begin(); + i != parser->interfaces.end(); + ++i) + { + Interface* interface = *i; + + for (vector::iterator j = interface->methods.begin(); + j != interface->methods.end(); + ++j) + { + Method* method = *j; + + bool isProcedure = method->returnTypeRef.token.type == Token::TYPE_VOID && + !method->returnTypeRef.isPointer; + + fprintf(out, "%s %s.%s(", + (isProcedure ? "procedure" : "function"), + escapeName(interface->name).c_str(), + escapeName(method->name).c_str()); + + for (vector::iterator k = method->parameters.begin(); + k != method->parameters.end(); + ++k) + { + Parameter* parameter = *k; + + if (k != method->parameters.begin()) + fprintf(out, "; "); + + fprintf(out, "%s", convertParameter(*parameter).c_str()); + } + + fprintf(out, ")"); + + if (!isProcedure) + fprintf(out, ": %s", convertType(method->returnTypeRef).c_str()); + + fprintf(out, ";\n"); + fprintf(out, "begin\n"); + fprintf(out, "\t"); + + //// TODO: checkVersion + + if (!isProcedure) + fprintf(out, "Result := "); + + fprintf(out, "%sVTable(vTable).%s(Self", + escapeName(interface->name).c_str(), escapeName(method->name).c_str()); + + for (vector::iterator k = method->parameters.begin(); + k != method->parameters.end(); + ++k) + { + Parameter* parameter = *k; + fprintf(out, ", %s", escapeName(parameter->name).c_str()); + } + + fprintf(out, ");\n"); + + if (!method->parameters.empty() && + parser->exceptionInterface && + method->parameters.front()->typeRef.token.text == parser->exceptionInterface->name && + !exceptionClass.empty()) + { + fprintf(out, "\t%s.checkException(%s);\n", exceptionClass.c_str(), + escapeName(method->parameters.front()->name).c_str()); + } + + fprintf(out, "end;\n\n"); + } + } + + for (vector::iterator i = parser->interfaces.begin(); + i != parser->interfaces.end(); + ++i) + { + Interface* interface = *i; + + deque methods; + + for (Interface* p = interface; p; p = p->super) + methods.insert(methods.begin(), p->methods.begin(), p->methods.end()); + + for (deque::iterator j = methods.begin(); j != methods.end(); ++j) + { + Method* method = *j; + + bool isProcedure = method->returnTypeRef.token.type == Token::TYPE_VOID && + !method->returnTypeRef.isPointer; + + fprintf(out, "%s %sImpl_%sDispatcher(this: %s", + (isProcedure ? "procedure" : "function"), + escapeName(interface->name).c_str(), + escapeName(method->name).c_str(), + escapeName(interface->name).c_str()); + + for (vector::iterator k = method->parameters.begin(); + k != method->parameters.end(); + ++k) + { + Parameter* parameter = *k; + + fprintf(out, "; %s", convertParameter(*parameter).c_str()); + } + + fprintf(out, ")"); + + if (!isProcedure) + fprintf(out, ": %s", convertType(method->returnTypeRef).c_str()); + + fprintf(out, "; cdecl;\n"); + fprintf(out, "begin\n"); + + if (!exceptionClass.empty()) + fprintf(out, "\ttry\n\t"); + + fprintf(out, "\t"); + + if (!isProcedure) + fprintf(out, "Result := "); + + fprintf(out, "%sImpl(this).%s(", escapeName(interface->name).c_str(), + escapeName(method->name).c_str()); + + for (vector::iterator k = method->parameters.begin(); + k != method->parameters.end(); + ++k) + { + Parameter* parameter = *k; + + if (k != method->parameters.begin()) + fprintf(out, ", "); + + fprintf(out, "%s", escapeName(parameter->name).c_str()); + } + + fprintf(out, ");\n"); + + if (!exceptionClass.empty()) + { + Parameter* exceptionParameter = + (!method->parameters.empty() && + parser->exceptionInterface && + method->parameters.front()->typeRef.token.text == parser->exceptionInterface->name + ) ? method->parameters.front() : NULL; + + fprintf(out, "\texcept\n"); + fprintf(out, "\t\ton e: Exception do %s.catchException(%s, e);\n", + exceptionClass.c_str(), + (exceptionParameter ? escapeName(exceptionParameter->name).c_str() : "nil")); + + fprintf(out, "\tend\n"); + } + + fprintf(out, "end;\n\n"); + } + + fprintf(out, "var\n"); + fprintf(out, "\t%sImpl_vTable: %sVTable;\n\n", + escapeName(interface->name).c_str(), escapeName(interface->name).c_str()); + + fprintf(out, "constructor %sImpl.create;\n", escapeName(interface->name).c_str()); + fprintf(out, "begin\n"); + fprintf(out, "\tvTable := %sImpl_vTable;\n", escapeName(interface->name).c_str()); + fprintf(out, "end;\n\n"); + } + + insertFile(implementationFile); + + fprintf(out, "initialization\n"); + + for (vector::iterator i = parser->interfaces.begin(); + i != parser->interfaces.end(); + ++i) + { + Interface* interface = *i; + + deque methods; + + for (Interface* p = interface; p; p = p->super) + methods.insert(methods.begin(), p->methods.begin(), p->methods.end()); + + fprintf(out, "\t%sImpl_vTable := %sVTable.create;\n", + escapeName(interface->name).c_str(), escapeName(interface->name).c_str()); + fprintf(out, "\t%sImpl_vTable.version := %d;\n", + escapeName(interface->name).c_str(), (int) methods.size()); + + for (deque::iterator j = methods.begin(); j != methods.end(); ++j) + { + Method* method = *j; + + fprintf(out, "\t%sImpl_vTable.%s := @%sImpl_%sDispatcher;\n", + escapeName(interface->name).c_str(), + escapeName(method->name).c_str(), + escapeName(interface->name).c_str(), + escapeName(method->name).c_str()); + } + + fprintf(out, "\n"); + } + + fprintf(out, "finalization\n"); + + for (vector::iterator i = parser->interfaces.begin(); + i != parser->interfaces.end(); + ++i) + { + Interface* interface = *i; + fprintf(out, "\t%sImpl_vTable.destroy;\n", escapeName(interface->name).c_str()); + } + + fprintf(out, "\n"); + fprintf(out, "end.\n"); +} + +string PascalGenerator::convertParameter(const Parameter& parameter) +{ + return escapeName(parameter.name) + ": " + convertType(parameter.typeRef); +} + +string PascalGenerator::convertType(const TypeRef& typeRef) +{ + string name; + + switch (typeRef.token.type) + { + case Token::TYPE_BOOLEAN: + name = "Boolean"; + break; + + case Token::TYPE_INT: + name = "Integer"; + break; + + case Token::TYPE_INT64: + name = "Int64"; + break; + + case Token::TYPE_INTPTR: + name = "NativeInt"; + break; + + case Token::TYPE_STRING: + name = "PAnsiChar"; + break; + + case Token::TYPE_UCHAR: + name = "Byte"; + break; + + case Token::TYPE_UINT: + name = "Cardinal"; + break; + + case Token::TYPE_UINT64: + name = "QWord"; + break; + + default: + name = typeRef.token.text; + break; + } + + if (typeRef.isPointer) + { + if (name == "void") + return "Pointer"; + + if (pointerTypes.find(name) == pointerTypes.end()) + pointerTypes.insert(name); + + name += "Ptr"; + } + + return name; +} + +string PascalGenerator::escapeName(const string& name) +{ + //// TODO: Create a table of keywords. + + if (name == "file" || + name == "function" || + name == "procedure" || + name == "set" || + name == "to" || + name == "type") + { + return name + "_"; + } + else + return name; +} + +void PascalGenerator::insertFile(const string& filename) +{ + if (filename.empty()) + return; + + FILE* in = fopen(filename.c_str(), "r"); + + if (!in) + throw runtime_error(string("Error opening input file '") + filename + "'."); + + char buffer[1024]; + int count; + + while ((count = fread(buffer, 1, sizeof(buffer), in)) > 0) + fwrite(buffer, 1, count, out); + + fclose(in); +} diff --git a/extern/cloop/src/cloop/Generator.h b/extern/cloop/src/cloop/Generator.h new file mode 100644 index 0000000000..6c8e3d1492 --- /dev/null +++ b/extern/cloop/src/cloop/Generator.h @@ -0,0 +1,148 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Adriano dos Santos Fernandes. + * + * Copyright (c) 2014 Adriano dos Santos Fernandes + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + */ + +#ifndef CLOOP_GENERATOR_H +#define CLOOP_GENERATOR_H + +#include "Parser.h" +#include +#include + + +#define DUMMY_VTABLE 1 +#define DUMMY_INSTANCE 1 + + +class Generator +{ +public: + virtual ~Generator() + { + } + + virtual void generate() = 0; + +protected: + static const char* const AUTOGEN_MSG; +}; + + +class FileGenerator : public Generator +{ +public: + FileGenerator(const std::string& filename, const std::string& prefix); + virtual ~FileGenerator(); + +protected: + FILE* out; + std::string prefix; +}; + + +class CBasedGenerator : public FileGenerator +{ +protected: + CBasedGenerator(const std::string& filename, const std::string& prefix, bool cPlusPlus); + +protected: + std::string convertType(const TypeRef& typeRef); + +protected: + bool cPlusPlus; +}; + + +class CppGenerator : public CBasedGenerator +{ +public: + CppGenerator(const std::string& filename, const std::string& prefix, Parser* parser, + const std::string& headerGuard, const std::string& nameSpace); + +public: + virtual void generate(); + +private: + Parser* parser; + std::string headerGuard; + std::string nameSpace; +}; + + +class CHeaderGenerator : public CBasedGenerator +{ +public: + CHeaderGenerator(const std::string& filename, const std::string& prefix, Parser* parser, + const std::string& headerGuard); + +public: + virtual void generate(); + +private: + Parser* parser; + std::string headerGuard; +}; + + +class CImplGenerator : public CBasedGenerator +{ +public: + CImplGenerator(const std::string& filename, const std::string& prefix, Parser* parser, + const std::string& includeFilename); + +public: + virtual void generate(); + +private: + Parser* parser; + std::string includeFilename; +}; + + +class PascalGenerator : public FileGenerator +{ +public: + PascalGenerator(const std::string& filename, const std::string& prefix, Parser* parser, + const std::string& unitName, const std::string& additionalUses, + const std::string& interfaceFile, const std::string& implementationFile, + const std::string& exceptionClass); + +public: + virtual void generate(); + +private: + std::string convertParameter(const Parameter& parameter); + std::string convertType(const TypeRef& typeRef); + std::string escapeName(const std::string& name); + + void insertFile(const std::string& filename); + +private: + Parser* parser; + std::string unitName; + std::string additionalUses; + std::string interfaceFile; + std::string implementationFile; + std::string exceptionClass; + std::set pointerTypes; +}; + + +#endif // CLOOP_GENERATOR_H diff --git a/extern/cloop/src/cloop/Lexer.cpp b/extern/cloop/src/cloop/Lexer.cpp new file mode 100644 index 0000000000..5027114ced --- /dev/null +++ b/extern/cloop/src/cloop/Lexer.cpp @@ -0,0 +1,261 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Adriano dos Santos Fernandes. + * + * Copyright (c) 2014 Adriano dos Santos Fernandes + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + */ + +#include "Lexer.h" +#include + +using std::runtime_error; +using std::string; + + +//-------------------------------------- + + +Lexer::Lexer(const string& filename) + : filename(filename), + line(1), + column(1) +{ + in = fopen(filename.c_str(), "r"); + + if (!in) + throw runtime_error(string("Input file not found: ") + filename + "."); +} + +Lexer::~Lexer() +{ + fclose(in); +} + +Token& Lexer::getToken(Token& token) +{ + if (!tokens.empty()) + { + token = tokens.top(); + tokens.pop(); + return token; + } + + token.text = ""; + + Char ch; + skip(ch); + + token.line = ch.line; + token.column = ch.column; + + if (ch.c == -1) + { + token.type = Token::TYPE_EOF; + return token; + } + else if ((ch.c >= 'a' && ch.c <= 'z') || (ch.c >= 'A' && ch.c <= 'Z') || ch.c == '_') + { + while ((ch.c >= 'a' && ch.c <= 'z') || (ch.c >= 'A' && ch.c <= 'Z') || ch.c == '_' || + (ch.c >= '0' && ch.c <= '9')) + { + token.text += ch.c; + getChar(ch); + } + + ungetChar(ch); + + // literals + if (token.text == "false" || token.text == "true") + token.type = Token::TYPE_BOOLEAN_LITERAL; + // keywords + else if (token.text == "const") + token.type = Token::TYPE_CONST; + else if (token.text == "exception") + token.type = Token::TYPE_EXCEPTION; + else if (token.text == "interface") + token.type = Token::TYPE_INTERFACE; + else if (token.text == "notImplemented") + token.type = Token::TYPE_NOT_IMPLEMENTED; + else if (token.text == "struct") + token.type = Token::TYPE_STRUCT; + else if (token.text == "typedef") + token.type = Token::TYPE_TYPEDEF; + else if (token.text == "version") + token.type = Token::TYPE_VERSION; + // types + else if (token.text == "void") + token.type = Token::TYPE_VOID; + else if (token.text == "boolean") + token.type = Token::TYPE_BOOLEAN; + else if (token.text == "int") + token.type = Token::TYPE_INT; + else if (token.text == "int64") + token.type = Token::TYPE_INT64; + else if (token.text == "intptr") + token.type = Token::TYPE_INTPTR; + else if (token.text == "string") + token.type = Token::TYPE_STRING; + else if (token.text == "uchar") + token.type = Token::TYPE_UCHAR; + else if (token.text == "uint") + token.type = Token::TYPE_UINT; + else if (token.text == "uint64") + token.type = Token::TYPE_UINT64; + else + token.type = Token::TYPE_IDENTIFIER; + } + else if (ch.c >= '0' && ch.c <= '9') + { + token.type = Token::TYPE_INT_LITERAL; + token.text += ch.c; + + if ((getChar(ch).c == 'x' || ch.c == 'X') && token.text[0] == '0') + { + token.text += ch.c; + + while ((getChar(ch).c >= '0' && ch.c <= '9') || + (tolower(ch.c) >= 'a' && tolower(ch.c) <= 'f')) + { + token.text += ch.c; + } + + if (token.text.length() == 2) + { + char buffer[1024]; + sprintf(buffer, "%s:%i:%i: error: Invalid hexadecimal prefix.", + filename.c_str(), line, column); + throw runtime_error(buffer); + } + } + else + { + ungetChar(ch); + + while (getChar(ch).c >= '0' && ch.c <= '9') + token.text += ch.c; + } + + ungetChar(ch); + } + else + { + token.type = static_cast(ch.c); + token.text = ch.c; + + if (getChar(ch).c == ':') + { + token.type = Token::TYPE_DOUBLE_COLON; + token.text += ch.c; + } + else + ungetChar(ch); + } + + return token; +} + +void Lexer::pushToken(const Token& token) +{ + tokens.push(token); +} + +void Lexer::skip(Char& ch) // skip spaces and comments +{ + while (true) + { + while (getChar(ch).c == ' ' || ch.c == '\t' || ch.c == '\r' || ch.c == '\n') + ; + + // check for comments + + if (ch.c != '/') + return; + + Char firstCh = ch; + getChar(ch); + + switch (ch.c) + { + case '*': + { + bool inComment = true; + + while (inComment) + { + while (getChar(ch).c != '*' && ch.c != -1) + ; + + if (ch.c == -1) + { + char buffer[1024]; + sprintf(buffer, "%s:%i:%i: error: Unterminated comment.", + filename.c_str(), + firstCh.line, firstCh.column); + throw runtime_error(buffer); + } + else + { + getChar(ch); + + if (ch.c == '/') + inComment = false; + else + ungetChar(ch); + } + } + + break; + } + + case '/': + while (getChar(ch).c != '\n' && ch.c != -1) + ; + + break; + + default: // not a comment + ch = firstCh; + break; + } + } + + // should never be here +} + +Lexer::Char& Lexer::getChar(Char& ch) +{ + ch.c = fgetc(in); + ch.line = line; + ch.column = column; + + if (ch.c == '\n') + { + ++line; + column = 1; + } + else + ++column; + + return ch; +} + +void Lexer::ungetChar(const Char& ch) +{ + ungetc(ch.c, in); + line = ch.line; + column = ch.column; +} diff --git a/extern/cloop/src/cloop/Lexer.h b/extern/cloop/src/cloop/Lexer.h new file mode 100644 index 0000000000..581254795d --- /dev/null +++ b/extern/cloop/src/cloop/Lexer.h @@ -0,0 +1,104 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Adriano dos Santos Fernandes. + * + * Copyright (c) 2014 Adriano dos Santos Fernandes + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + */ + +#ifndef CLOOP_LEXER_H +#define CLOOP_LEXER_H + +#include +#include +#include + + +#define TOKEN(c) static_cast< ::Token::Type>(c) + + +struct Token +{ + enum Type + { + TYPE_EOF = 256, + TYPE_IDENTIFIER, + // punctuation + TYPE_DOUBLE_COLON, + // literals + TYPE_BOOLEAN_LITERAL, + TYPE_INT_LITERAL, + // keywords + TYPE_CONST, + TYPE_EXCEPTION, + TYPE_INTERFACE, + TYPE_NOT_IMPLEMENTED, + TYPE_STRUCT, + TYPE_TYPEDEF, + TYPE_VERSION, + // types + TYPE_VOID, + TYPE_BOOLEAN, + TYPE_INT, + TYPE_INT64, + TYPE_INTPTR, + TYPE_STRING, + TYPE_UCHAR, + TYPE_UINT, + TYPE_UINT64 + }; + + Type type; + std::string text; + unsigned line; + unsigned column; +}; + + +class Lexer +{ +private: + struct Char + { + int c; + unsigned line; + unsigned column; + }; + +public: + Lexer(const std::string& filename); + ~Lexer(); + +public: + Token& getToken(Token& token); + void pushToken(const Token& token); + +private: + void skip(Char& ch); + Char& getChar(Char& ch); + void ungetChar(const Char& ch); + +public: + const std::string filename; + +private: + FILE* in; + unsigned line, column; + std::stack tokens; +}; + + +#endif // CLOOP_LEXER_H diff --git a/extern/cloop/src/cloop/Main.cpp b/extern/cloop/src/cloop/Main.cpp new file mode 100644 index 0000000000..ab57898797 --- /dev/null +++ b/extern/cloop/src/cloop/Main.cpp @@ -0,0 +1,123 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Adriano dos Santos Fernandes. + * + * Copyright (c) 2014 Adriano dos Santos Fernandes + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + */ + +#include "Lexer.h" +#include "Parser.h" +#include "Expr.h" +#include "Generator.h" +#include +#include +#include +#include + +using std::auto_ptr; +using std::cerr; +using std::endl; +using std::exception; +using std::string; +using std::runtime_error; + + +//-------------------------------------- + + +static void run(int argc, const char* argv[]) +{ + if (argc < 4) + throw runtime_error("Invalid command line parameters."); + + string inFilename(argv[1]); + string outFormat(argv[2]); + string outFilename(argv[3]); + + Lexer lexer(inFilename); + + Parser parser(&lexer); + parser.parse(); + + auto_ptr generator; + + if (outFormat == "c++") + { + if (argc < 7) + throw runtime_error("Invalid command line parameters for C++ output."); + + string headerGuard(argv[4]); + string className(argv[5]); + string prefix(argv[6]); + + generator.reset(new CppGenerator(outFilename, prefix, &parser, headerGuard, className)); + } + else if (outFormat == "c-header") + { + if (argc < 6) + throw runtime_error("Invalid command line parameters for C header output."); + + string headerGuard(argv[4]); + string prefix(argv[5]); + + generator.reset(new CHeaderGenerator(outFilename, prefix, &parser, headerGuard)); + } + else if (outFormat == "c-impl") + { + if (argc < 6) + throw runtime_error("Invalid command line parameters for C implementation output."); + + string includeFilename(argv[4]); + string prefix(argv[5]); + + generator.reset(new CImplGenerator(outFilename, prefix, &parser, includeFilename)); + } + else if (outFormat == "pascal") + { + if (argc < 5) + throw runtime_error("Invalid command line parameters for Pascal output."); + + string unitName(argv[4]); + string additionalUses(argc > 5 ? argv[5] : ""); + string interfaceFile(argc > 6 ? argv[6] : ""); + string implementationFile(argc > 7 ? argv[7] : ""); + string exceptionClass(argc > 8 ? argv[8] : ""); + string prefix; //// TODO: + + generator.reset(new PascalGenerator(outFilename, prefix, &parser, unitName, + additionalUses, interfaceFile, implementationFile, exceptionClass)); + } + else + throw runtime_error("Invalid output format."); + + generator->generate(); +} + + +int main(int argc, const char* argv[]) +{ + try + { + run(argc, argv); + return 0; + } + catch (exception& e) + { + cerr << e.what() << endl; + return 1; + } +} diff --git a/extern/cloop/src/cloop/Parser.cpp b/extern/cloop/src/cloop/Parser.cpp new file mode 100644 index 0000000000..00d56a32b5 --- /dev/null +++ b/extern/cloop/src/cloop/Parser.cpp @@ -0,0 +1,418 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Adriano dos Santos Fernandes. + * + * Copyright (c) 2014 Adriano dos Santos Fernandes + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + */ + +#include "Parser.h" +#include "Expr.h" +#include +#include +#include + +using std::map; +using std::pair; +using std::runtime_error; +using std::string; +using std::vector; + + +//-------------------------------------- + + +Parser::Parser(Lexer* lexer) + : exceptionInterface(NULL), + lexer(lexer), + interface(NULL) +{ +} + +void Parser::parse() +{ + interface = NULL; + + while (true) + { + bool exception = false; + lexer->getToken(token); + + if (token.type == Token::TYPE_EOF) + break; + else if (token.type == TOKEN('[')) + { + getToken(token, Token::TYPE_EXCEPTION); // This is the only attribute we allow now. + exception = true; + getToken(token, TOKEN(']')); + } + else + lexer->pushToken(token); + + lexer->getToken(token); + + switch (token.type) + { + case Token::TYPE_INTERFACE: + parseInterface(exception); + break; + + case Token::TYPE_STRUCT: + if (exception) + error(token, "Cannot use attribute exception in struct."); + parseStruct(); + break; + + case Token::TYPE_TYPEDEF: + if (exception) + error(token, "Cannot use attribute exception in typedef."); + parseTypedef(); + break; + + default: + syntaxError(token); + break; + } + } + + // Check types. + + for (vector::iterator i = interfaces.begin(); i != interfaces.end(); ++i) + { + Interface* interface = *i; + + for (vector::iterator j = interface->methods.begin(); + j != interface->methods.end(); + ++j) + { + Method* method = *j; + + checkType(method->returnTypeRef); + + for (vector::iterator k = method->parameters.begin(); + k != method->parameters.end(); + ++k) + { + Parameter* parameter = *k; + checkType(parameter->typeRef); + } + } + } +} + +void Parser::parseInterface(bool exception) +{ + interface = new Interface(); + interfaces.push_back(interface); + + interface->name = getToken(token, Token::TYPE_IDENTIFIER).text; + typesByName.insert(pair(interface->name, interface)); + + if (exception) + exceptionInterface = interface; + + if (lexer->getToken(token).type == TOKEN(':')) + { + string superName = getToken(token, Token::TYPE_IDENTIFIER).text; + map::iterator it = typesByName.find(superName); + + if (it == typesByName.end() || it->second->type != BaseType::TYPE_INTERFACE) + error(token, string("Super interface '") + superName + "' not found."); + + interface->super = static_cast(it->second); + interface->version = interface->super->version + 1; + } + else + lexer->pushToken(token); + + getToken(token, TOKEN('{')); + + while (lexer->getToken(token).type != TOKEN('}')) + { + if (token.type == Token::TYPE_VERSION) + { + getToken(token, TOKEN(':')); + ++interface->version; + } + else + lexer->pushToken(token); + + parseItem(); + } +} + +void Parser::parseStruct() +{ + Struct* ztruct = new Struct(); + + ztruct->name = getToken(token, Token::TYPE_IDENTIFIER).text; + typesByName.insert(pair(ztruct->name, ztruct)); + + getToken(token, TOKEN(';')); +} + +void Parser::parseTypedef() +{ + Typedef* typeDef = new Typedef(); + + typeDef->name = getToken(token, Token::TYPE_IDENTIFIER).text; + typesByName.insert(pair(typeDef->name, typeDef)); + + getToken(token, TOKEN(';')); +} + +void Parser::parseItem() +{ + Expr* notImplementedExpr = NULL; + + lexer->getToken(token); + + if (token.type == TOKEN('[')) + { + getToken(token, Token::TYPE_NOT_IMPLEMENTED); // This is the only attribute we allow now. + getToken(token, TOKEN('(')); + notImplementedExpr = parseExpr(); + getToken(token, TOKEN(')')); + getToken(token, TOKEN(']')); + } + else + lexer->pushToken(token); + + TypeRef typeRef(parseTypeRef()); + string name(getToken(token, Token::TYPE_IDENTIFIER).text); + + if (!notImplementedExpr && typeRef.isConst) + { + if (lexer->getToken(token).type == TOKEN('=')) + { + typeRef.isConst = false; + parseConstant(typeRef, name); + return; + } + else + lexer->pushToken(token); + } + + getToken(token, TOKEN('(')); + parseMethod(typeRef, name, notImplementedExpr); +} + +void Parser::parseConstant(const TypeRef& typeRef, const string& name) +{ + Constant* constant = new Constant(); + interface->constants.push_back(constant); + + constant->typeRef = typeRef; + constant->name = name; + constant->expr = parseExpr(); + + getToken(token, TOKEN(';')); +} + +void Parser::parseMethod(const TypeRef& returnTypeRef, const string& name, Expr* notImplementedExpr) +{ + Method* method = new Method(); + interface->methods.push_back(method); + + method->returnTypeRef = returnTypeRef; + method->name = name; + method->version = interface->version; + method->notImplementedExpr = notImplementedExpr; + + if (lexer->getToken(token).type != TOKEN(')')) + { + lexer->pushToken(token); + + while (true) + { + Parameter* parameter = new Parameter(); + method->parameters.push_back(parameter); + + parameter->typeRef = parseTypeRef(); + parameter->name = getToken(token, Token::TYPE_IDENTIFIER).text; + + lexer->getToken(token); + lexer->pushToken(token); + + if (token.type == TOKEN(')')) + break; + + getToken(token, TOKEN(',')); + } + + getToken(token, TOKEN(')')); + } + + if (lexer->getToken(token).type == Token::TYPE_CONST) + method->isConst = true; + else + lexer->pushToken(token); + + getToken(token, TOKEN(';')); +} + +Expr* Parser::parseExpr() +{ + return parseLogicalExpr(); +} + +Expr* Parser::parseLogicalExpr() +{ + Expr* expr = parseUnaryExpr(); + + if (lexer->getToken(token).type == TOKEN('|')) + expr = new BitwiseOrExpr(expr, parseExpr()); + else + lexer->pushToken(token); + + return expr; +} + +Expr* Parser::parseUnaryExpr() +{ + lexer->getToken(token); + + if (token.type == TOKEN('-')) + return new NegateExpr(parsePrimaryExpr()); + else + { + lexer->pushToken(token); + return parsePrimaryExpr(); + } +} + +Expr* Parser::parsePrimaryExpr() +{ + lexer->getToken(token); + + switch (token.type) + { + case Token::TYPE_BOOLEAN_LITERAL: + return new BooleanLiteralExpr(token.text == "true"); + + case Token::TYPE_INT_LITERAL: + { + const char* p = token.text.c_str(); + size_t len = strlen(p); + int base = len > 2 && tolower(p[1]) == 'x' ? 16 : 10; + long val = strtol(p, NULL, base); + + return new IntLiteralExpr((int) val); + } + + case Token::TYPE_IDENTIFIER: + { + string text = token.text; + + if (lexer->getToken(token).type == Token::TYPE_DOUBLE_COLON) + { + getToken(token, Token::TYPE_IDENTIFIER); + map::iterator it = typesByName.find(text); + + if (it == typesByName.end() || it->second->type != BaseType::TYPE_INTERFACE) + error(token, string("Interface '") + text + "' not found."); + + return new ConstantExpr(static_cast(it->second), token.text); + } + else + { + lexer->pushToken(token); + return new ConstantExpr(interface, text); + } + } + + default: + syntaxError(token); + return NULL; // warning + } +} + +void Parser::checkType(TypeRef& typeRef) +{ + if (typeRef.token.type == Token::TYPE_IDENTIFIER) + { + map::iterator it = typesByName.find(typeRef.token.text); + + if (it != typesByName.end()) + typeRef.type = it->second->type; + else + error(typeRef.token, string("Interface/struct '") + typeRef.token.text + "' not found."); + } +} + +Token& Parser::getToken(Token& token, Token::Type expected, bool allowEof) +{ + lexer->getToken(token); + + if (token.type != expected && !(allowEof && token.type == Token::TYPE_EOF)) + syntaxError(token); + + return token; +} + +TypeRef Parser::parseTypeRef() +{ + TypeRef typeRef; + lexer->getToken(typeRef.token); + + if (typeRef.token.type == Token::TYPE_CONST) + { + typeRef.isConst = true; + lexer->getToken(typeRef.token); + } + + switch (typeRef.token.type) + { + case Token::TYPE_VOID: + case Token::TYPE_BOOLEAN: + case Token::TYPE_INT: + case Token::TYPE_INT64: + case Token::TYPE_INTPTR: + case Token::TYPE_STRING: + case Token::TYPE_UCHAR: + case Token::TYPE_UINT: + case Token::TYPE_UINT64: + case Token::TYPE_IDENTIFIER: + break; + + default: + error(typeRef.token, string("Syntax error at '") + + typeRef.token.text + "'. Expected a type."); + break; + } + + Token token2; + lexer->getToken(token2); + if (token2.type == TOKEN('*')) + typeRef.isPointer = true; + else + lexer->pushToken(token2); + + return typeRef; +} + +void Parser::syntaxError(const Token& token) +{ + error(token, string("Syntax error at '") + token.text + "'."); +} + +void Parser::error(const Token& token, const string& msg) +{ + char buffer[1024]; + sprintf(buffer, "%s:%i:%i: error: %s", + lexer->filename.c_str(), token.line, token.column, msg.c_str()); + throw runtime_error(buffer); +} diff --git a/extern/cloop/src/cloop/Parser.h b/extern/cloop/src/cloop/Parser.h new file mode 100644 index 0000000000..cd609ed526 --- /dev/null +++ b/extern/cloop/src/cloop/Parser.h @@ -0,0 +1,191 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Adriano dos Santos Fernandes. + * + * Copyright (c) 2014 Adriano dos Santos Fernandes + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + */ + +#ifndef CLOOP_PARSER_H +#define CLOOP_PARSER_H + +#include "Lexer.h" +#include +#include +#include + + +class Expr; + + +class BaseType +{ +public: + enum Type + { + TYPE_INTERFACE, + TYPE_STRUCT, + TYPE_TYPEDEF + }; + +protected: + BaseType(Type type) + : type(type) + { + } + + virtual ~BaseType() + { + } + +public: + Type type; + std::string name; +}; + + +class TypeRef +{ +public: + TypeRef() + : isConst(false), + isPointer(false), + type(BaseType::TYPE_INTERFACE) + { + } + + Token token; + bool isConst; + bool isPointer; + BaseType::Type type; +}; + + +class Parameter +{ +public: + std::string name; + TypeRef typeRef; +}; + + +class Constant +{ +public: + std::string name; + TypeRef typeRef; + Expr* expr; +}; + + +class Method +{ +public: + Method() + : notImplementedExpr(NULL), + version(0), + isConst(false) + { + } + + std::string name; + TypeRef returnTypeRef; + std::vector parameters; + Expr* notImplementedExpr; + unsigned version; + bool isConst; +}; + + +class Interface : public BaseType +{ +public: + Interface() + : BaseType(TYPE_INTERFACE), + super(NULL), + version(1) + { + } + +public: + Interface* super; + std::vector constants; + std::vector methods; + unsigned version; +}; + + +class Struct : public BaseType +{ +public: + Struct() + : BaseType(TYPE_STRUCT) + { + } +}; + + +class Typedef : public BaseType +{ +public: + Typedef() + : BaseType(TYPE_TYPEDEF) + { + } +}; + + +class Parser +{ +public: + Parser(Lexer* lexer); + + void parse(); + void parseInterface(bool exception); + void parseStruct(); + void parseTypedef(); + void parseItem(); + void parseConstant(const TypeRef& typeRef, const std::string& name); + void parseMethod(const TypeRef& returnTypeRef, const std::string& name, Expr* notImplementedExpr); + + Expr* parseExpr(); + Expr* parseLogicalExpr(); + Expr* parseUnaryExpr(); + Expr* parsePrimaryExpr(); + +private: + void checkType(TypeRef& typeRef); + + Token& getToken(Token& token, Token::Type expected, bool allowEof = false); + + TypeRef parseTypeRef(); + + void syntaxError(const Token& token); + void error(const Token& token, const std::string& msg); + +public: + std::vector interfaces; + std::map typesByName; + Interface* exceptionInterface; + +private: + Lexer* lexer; + Token token; + Interface* interface; +}; + + +#endif // CLOOP_PARSER_H diff --git a/extern/cloop/src/cloop/cloop.vcxproj b/extern/cloop/src/cloop/cloop.vcxproj new file mode 100644 index 0000000000..d2473ce158 --- /dev/null +++ b/extern/cloop/src/cloop/cloop.vcxproj @@ -0,0 +1,149 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + Win32Proj + + + + Application + true + + + Application + true + + + Application + false + + + Application + false + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)\output\$(Configuration)\bin\ + $(SolutionDir)\build\$(Configuration)\$(ProjectName)\ + + + true + $(SolutionDir)\output\$(Configuration)\bin\ + $(SolutionDir)\build\$(Configuration)\$(ProjectName)\ + + + true + $(SolutionDir)\output\$(Configuration)\bin\ + $(SolutionDir)\build\$(Configuration)\$(ProjectName)\ + + + true + $(SolutionDir)\output\$(Configuration)\bin\ + $(SolutionDir)\build\$(Configuration)\$(ProjectName)\ + + + + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + + + MachineX86 + true + Console + + + + + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + + + true + Console + + + + + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + MachineX86 + true + Console + true + true + + + + + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + true + Console + true + true + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/extern/cloop/src/cloop/cloop.vcxproj.filters b/extern/cloop/src/cloop/cloop.vcxproj.filters new file mode 100644 index 0000000000..ddc5356061 --- /dev/null +++ b/extern/cloop/src/cloop/cloop.vcxproj.filters @@ -0,0 +1,48 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/extern/cloop/src/tests/test1/CTest.c b/extern/cloop/src/tests/test1/CTest.c new file mode 100644 index 0000000000..a3739ce411 --- /dev/null +++ b/extern/cloop/src/tests/test1/CTest.c @@ -0,0 +1,418 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Adriano dos Santos Fernandes. + * + * Copyright (c) 2014 Adriano dos Santos Fernandes + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + */ + +#include "CalcCApi.h" +#include +#include + +#ifdef WIN32 +#include +#define DLL_EXPORT __declspec(dllexport) +#else +#include +#define DLL_EXPORT +#endif + + +//-------------------------------------- + +// CALC_IStatusImpl + + +struct CALC_IStatusImpl +{ + void* cloopDummy; + struct CALC_IStatusVTable* vtable; + int code; +}; + +static void CALC_IStatusImpl_dispose(struct CALC_IStatus* self) +{ + free(self); +} + +static int CALC_IStatusImpl_getCode(const struct CALC_IStatus* self) +{ + return ((struct CALC_IStatusImpl*) self)->code; +} + +static void CALC_IStatusImpl_setCode(struct CALC_IStatus* self, int code) +{ + ((struct CALC_IStatusImpl*) self)->code = code; +} + +struct CALC_IStatus* CALC_IStatusImpl_create() +{ + static struct CALC_IStatusVTable vtable = { + {NULL}, + CALC_IStatus_VERSION, + CALC_IStatusImpl_dispose, + CALC_IStatusImpl_getCode, + CALC_IStatusImpl_setCode + }; + + struct CALC_IStatusImpl* impl = malloc(sizeof(struct CALC_IStatusImpl)); + impl->vtable = &vtable; + impl->code = 0; + + return (struct CALC_IStatus*) impl; +} + + +//-------------------------------------- + +// CALC_ICalculatorImpl + + +struct CALC_ICalculatorImpl +{ + void* cloopDummy; + struct CALC_ICalculatorVTable* vtable; + int memory; +}; + +static void CALC_ICalculatorImpl_dispose(struct CALC_ICalculator* self) +{ + free(self); +} + +static int CALC_ICalculatorImpl_sum(const struct CALC_ICalculator* self, + struct CALC_IStatus* status, int n1, int n2) +{ + if (n1 + n2 > 1000) + { + CALC_IStatus_setCode(status, CALC_IStatus_ERROR_1); + return 0; + } + else + return n1 + n2; +} + +static int CALC_ICalculatorImpl_getMemory(const struct CALC_ICalculator* self) +{ + return ((struct CALC_ICalculatorImpl*) self)->memory; +} + +static void CALC_ICalculatorImpl_setMemory(struct CALC_ICalculator* self, int n) +{ + ((struct CALC_ICalculatorImpl*) self)->memory = n; +} + +static void CALC_ICalculatorImpl_sumAndStore(struct CALC_ICalculator* self, + struct CALC_IStatus* status, int n1, int n2) +{ + CALC_ICalculator_setMemory(self, CALC_ICalculator_sum(self, status, n1, n2)); +} + +struct CALC_ICalculator* CALC_ICalculatorImpl_create() +{ + static struct CALC_ICalculatorVTable vtable = { + {NULL}, + CALC_ICalculator_VERSION, + CALC_ICalculatorImpl_dispose, + CALC_ICalculatorImpl_sum, + CALC_ICalculatorImpl_getMemory, + CALC_ICalculatorImpl_setMemory, + CALC_ICalculatorImpl_sumAndStore + }; + + struct CALC_ICalculatorImpl* impl = malloc(sizeof(struct CALC_ICalculatorImpl)); + impl->vtable = &vtable; + impl->memory = 0; + + return (struct CALC_ICalculator*) impl; +} + + +//-------------------------------------- + +// CALC_ICalculator2Impl + + +struct CALC_ICalculator2Impl +{ + void* cloopDummy; + struct CALC_ICalculator2VTable* vtable; + int memory; +}; + +static void CALC_ICalculator2Impl_dispose(struct CALC_ICalculator2* self) +{ + free(self); +} + +static int CALC_ICalculator2Impl_sum(const struct CALC_ICalculator2* self, + struct CALC_IStatus* status, int n1, int n2) +{ + if (n1 + n2 > 1000) + { + CALC_IStatus_setCode(status, CALC_IStatus_ERROR_1); + return 0; + } + else + return n1 + n2; +} + +static int CALC_ICalculator2Impl_getMemory(const struct CALC_ICalculator2* self) +{ + return ((struct CALC_ICalculator2Impl*) self)->memory; +} + +static void CALC_ICalculator2Impl_setMemory(struct CALC_ICalculator2* self, int n) +{ + ((struct CALC_ICalculator2Impl*) self)->memory = n; +} + +static void CALC_ICalculator2Impl_sumAndStore(struct CALC_ICalculator2* self, + struct CALC_IStatus* status, int n1, int n2) +{ + CALC_ICalculator2_setMemory(self, CALC_ICalculator2_sum(self, status, n1, n2)); +} + +static int CALC_ICalculator2Impl_multiply(const struct CALC_ICalculator2* self, + struct CALC_IStatus* status, int n1, int n2) +{ + return n1 * n2; +} + +static void CALC_ICalculator2Impl_copyMemory(struct CALC_ICalculator2* self, + const struct CALC_ICalculator* calculator) +{ + CALC_ICalculator2_setMemory(self, CALC_ICalculator_getMemory(calculator)); +} + +static void CALC_ICalculator2Impl_copyMemory2(struct CALC_ICalculator2* self, const int* address) +{ + CALC_ICalculator2_setMemory(self, *address); +} + +struct CALC_ICalculator2* CALC_ICalculator2Impl_create() +{ + static struct CALC_ICalculator2VTable vtable = { + {NULL}, + CALC_ICalculator2_VERSION, + CALC_ICalculator2Impl_dispose, + CALC_ICalculator2Impl_sum, + CALC_ICalculator2Impl_getMemory, + CALC_ICalculator2Impl_setMemory, + CALC_ICalculator2Impl_sumAndStore, + CALC_ICalculator2Impl_multiply, + CALC_ICalculator2Impl_copyMemory, + CALC_ICalculator2Impl_copyMemory2 + }; + + struct CALC_ICalculator2Impl* impl = malloc(sizeof(struct CALC_ICalculator2Impl)); + impl->vtable = &vtable; + impl->memory = 0; + + return (struct CALC_ICalculator2*) impl; +} + + +//-------------------------------------- + +// CALC_IBrokenCalculatorImpl + + +static int CALC_IBrokenCalculatorImpl_sum(const struct CALC_ICalculator* self, + struct CALC_IStatus* status, int n1, int n2) +{ + return CALC_ICalculatorImpl_sum(self, status, n1, n2) + 1; +} + +struct CALC_ICalculator* CALC_IBrokenCalculatorImpl_create() +{ + static struct CALC_ICalculatorVTable vtable = { + {NULL}, + CALC_ICalculator_VERSION, + CALC_ICalculatorImpl_dispose, + CALC_IBrokenCalculatorImpl_sum, + CALC_ICalculatorImpl_getMemory, + CALC_ICalculatorImpl_setMemory, + CALC_ICalculatorImpl_sumAndStore + }; + + struct CALC_ICalculatorImpl* impl = malloc(sizeof(struct CALC_ICalculatorImpl)); + impl->vtable = &vtable; + impl->memory = 0; + + return (struct CALC_ICalculator*) impl; +} + + +//-------------------------------------- + +// CALC_IFactoryImpl + + +static void CALC_IFactoryImpl_dispose(struct CALC_IFactory* self) +{ + free(self); +} + +static struct CALC_IStatus* CALC_IFactoryImpl_createStatus(struct CALC_IFactory* self) +{ + return CALC_IStatusImpl_create(); +} + +static struct CALC_ICalculator* CALC_IFactoryImpl_createCalculator(struct CALC_IFactory* self, + struct CALC_IStatus* status) +{ + return CALC_ICalculatorImpl_create(); +} + +static struct CALC_ICalculator2* CALC_IFactoryImpl_createCalculator2(struct CALC_IFactory* self, + struct CALC_IStatus* status) +{ + return CALC_ICalculator2Impl_create(); +} + +static struct CALC_ICalculator* CALC_IFactoryImpl_createBrokenCalculator(struct CALC_IFactory* self, + struct CALC_IStatus* status) +{ + return CALC_IBrokenCalculatorImpl_create(); +} + +struct CALC_IFactory* CALC_IFactoryImpl_create() +{ + static struct CALC_IFactoryVTable vtable = { + {NULL}, + CALC_IFactory_VERSION, + CALC_IFactoryImpl_dispose, + CALC_IFactoryImpl_createStatus, + CALC_IFactoryImpl_createCalculator, + CALC_IFactoryImpl_createCalculator2, + CALC_IFactoryImpl_createBrokenCalculator + }; + + struct CALC_IFactory* impl = malloc(sizeof(struct CALC_IFactory)); + impl->vtable = &vtable; + + return impl; +} + + +//-------------------------------------- + +// Library entry point + + +DLL_EXPORT struct CALC_IFactory* createFactory() +{ + return CALC_IFactoryImpl_create(); +} + + +//-------------------------------------- + + +static void test(struct CALC_IFactory* (*createFactory)()) +{ + struct CALC_IFactory* factory = createFactory(); + struct CALC_IStatus* status = (struct CALC_IStatus*) CALC_IStatusImpl_create(); + struct CALC_ICalculator* calculator; + struct CALC_ICalculator2* calculator2; + int sum, code, address; + + calculator = CALC_IFactory_createCalculator(factory, status); + + address = 40; + + CALC_ICalculator_sumAndStore(calculator, status, 1, 22); + printf("%d\n", CALC_ICalculator_getMemory(calculator)); // 23 + + CALC_ICalculator_setMemory(calculator, CALC_ICalculator_sum(calculator, status, 2, 33)); + printf("%d\n", CALC_ICalculator_getMemory(calculator)); // 35 + + calculator2 = CALC_IFactory_createCalculator2(factory, status); + + CALC_ICalculator2_copyMemory(calculator2, calculator); + printf("%d\n", CALC_ICalculator2_getMemory(calculator2)); // 35 + + CALC_ICalculator2_copyMemory2(calculator2, &address); + printf("%d\n", CALC_ICalculator2_getMemory(calculator2)); // 40 + + CALC_ICalculator_dispose(calculator); + calculator = (struct CALC_ICalculator*) calculator2; + + CALC_ICalculator_sumAndStore(calculator, status, 1, 22); + printf("%d\n", CALC_ICalculator_getMemory(calculator)); // 23 + + CALC_ICalculator_setMemory(calculator, CALC_ICalculator_sum(calculator, status, 2, 33)); + printf("%d\n", CALC_ICalculator_getMemory(calculator)); // 35 + + CALC_ICalculator2_sumAndStore(calculator2, status, 1, 22); + printf("%d\n", CALC_ICalculator2_getMemory(calculator2)); // 23 + + CALC_ICalculator2_setMemory(calculator2, CALC_ICalculator2_multiply(calculator2, status, 2, 33)); + printf("%d\n", CALC_ICalculator2_getMemory(calculator2)); // 66 + + CALC_ICalculator_dispose(calculator); + + calculator = CALC_IFactory_createBrokenCalculator(factory, status); + + CALC_ICalculator_sumAndStore(calculator, status, 1, 22); + printf("%d\n", CALC_ICalculator_getMemory(calculator)); // 24 + + CALC_ICalculator_setMemory(calculator, CALC_ICalculator_sum(calculator, status, 2, 33)); + printf("%d\n", CALC_ICalculator_getMemory(calculator)); // 36 + + sum = CALC_ICalculator_sum(calculator, status, 600, 600); + code = CALC_IStatus_getCode(status); + if (code != 0) + printf("exception %d\n", code); // exception 1 + else + printf("%d\n", sum); + + CALC_ICalculator_dispose(calculator); + + CALC_IStatus_dispose(status); + CALC_IFactory_dispose(factory); + + printf("\n"); +} + +int main(int argc, char* argv[]) +{ +#ifdef WIN32 + HMODULE library = LoadLibrary(argv[1]); +#else + void* library = dlopen(argv[1], RTLD_LAZY); +#endif + + struct CALC_IFactory* (*createFactory)(); + +#ifdef WIN32 + createFactory = (struct Factory* (*)()) GetProcAddress(library, "createFactory"); +#else + createFactory = dlsym(library, "createFactory"); +#endif + + test(createFactory); + +#ifdef WIN32 + FreeLibrary(library); +#else + dlclose(library); +#endif + + return 0; +} diff --git a/extern/cloop/src/tests/test1/CalcCApi.c b/extern/cloop/src/tests/test1/CalcCApi.c new file mode 100644 index 0000000000..ca87c06cac --- /dev/null +++ b/extern/cloop/src/tests/test1/CalcCApi.c @@ -0,0 +1,115 @@ +/* This file was autogenerated by cloop - Cross Language Object Oriented Programming */ + +#include "CalcCApi.h" + + +CLOOP_EXTERN_C void CALC_IDisposable_dispose(struct CALC_IDisposable* self) +{ + self->vtable->dispose(self); +} + +CLOOP_EXTERN_C void CALC_IStatus_dispose(struct CALC_IStatus* self) +{ + self->vtable->dispose(self); +} + +CLOOP_EXTERN_C int CALC_IStatus_getCode(const struct CALC_IStatus* self) +{ + return self->vtable->getCode(self); +} + +CLOOP_EXTERN_C void CALC_IStatus_setCode(struct CALC_IStatus* self, int code) +{ + self->vtable->setCode(self, code); +} + +CLOOP_EXTERN_C void CALC_IFactory_dispose(struct CALC_IFactory* self) +{ + self->vtable->dispose(self); +} + +CLOOP_EXTERN_C struct CALC_IStatus* CALC_IFactory_createStatus(struct CALC_IFactory* self) +{ + return self->vtable->createStatus(self); +} + +CLOOP_EXTERN_C struct CALC_ICalculator* CALC_IFactory_createCalculator(struct CALC_IFactory* self, struct CALC_IStatus* status) +{ + return self->vtable->createCalculator(self, status); +} + +CLOOP_EXTERN_C struct CALC_ICalculator2* CALC_IFactory_createCalculator2(struct CALC_IFactory* self, struct CALC_IStatus* status) +{ + return self->vtable->createCalculator2(self, status); +} + +CLOOP_EXTERN_C struct CALC_ICalculator* CALC_IFactory_createBrokenCalculator(struct CALC_IFactory* self, struct CALC_IStatus* status) +{ + return self->vtable->createBrokenCalculator(self, status); +} + +CLOOP_EXTERN_C void CALC_ICalculator_dispose(struct CALC_ICalculator* self) +{ + self->vtable->dispose(self); +} + +CLOOP_EXTERN_C int CALC_ICalculator_sum(const struct CALC_ICalculator* self, struct CALC_IStatus* status, int n1, int n2) +{ + return self->vtable->sum(self, status, n1, n2); +} + +CLOOP_EXTERN_C int CALC_ICalculator_getMemory(const struct CALC_ICalculator* self) +{ + return self->vtable->getMemory(self); +} + +CLOOP_EXTERN_C void CALC_ICalculator_setMemory(struct CALC_ICalculator* self, int n) +{ + self->vtable->setMemory(self, n); +} + +CLOOP_EXTERN_C void CALC_ICalculator_sumAndStore(struct CALC_ICalculator* self, struct CALC_IStatus* status, int n1, int n2) +{ + self->vtable->sumAndStore(self, status, n1, n2); +} + +CLOOP_EXTERN_C void CALC_ICalculator2_dispose(struct CALC_ICalculator2* self) +{ + self->vtable->dispose(self); +} + +CLOOP_EXTERN_C int CALC_ICalculator2_sum(const struct CALC_ICalculator2* self, struct CALC_IStatus* status, int n1, int n2) +{ + return self->vtable->sum(self, status, n1, n2); +} + +CLOOP_EXTERN_C int CALC_ICalculator2_getMemory(const struct CALC_ICalculator2* self) +{ + return self->vtable->getMemory(self); +} + +CLOOP_EXTERN_C void CALC_ICalculator2_setMemory(struct CALC_ICalculator2* self, int n) +{ + self->vtable->setMemory(self, n); +} + +CLOOP_EXTERN_C void CALC_ICalculator2_sumAndStore(struct CALC_ICalculator2* self, struct CALC_IStatus* status, int n1, int n2) +{ + self->vtable->sumAndStore(self, status, n1, n2); +} + +CLOOP_EXTERN_C int CALC_ICalculator2_multiply(const struct CALC_ICalculator2* self, struct CALC_IStatus* status, int n1, int n2) +{ + return self->vtable->multiply(self, status, n1, n2); +} + +CLOOP_EXTERN_C void CALC_ICalculator2_copyMemory(struct CALC_ICalculator2* self, const struct CALC_ICalculator* calculator) +{ + self->vtable->copyMemory(self, calculator); +} + +CLOOP_EXTERN_C void CALC_ICalculator2_copyMemory2(struct CALC_ICalculator2* self, const int* address) +{ + self->vtable->copyMemory2(self, address); +} + diff --git a/extern/cloop/src/tests/test1/CalcCApi.h b/extern/cloop/src/tests/test1/CalcCApi.h new file mode 100644 index 0000000000..ac9e3317a4 --- /dev/null +++ b/extern/cloop/src/tests/test1/CalcCApi.h @@ -0,0 +1,158 @@ +/* This file was autogenerated by cloop - Cross Language Object Oriented Programming */ + +#ifndef CALC_C_API_H +#define CALC_C_API_H + +#include + +#ifndef CLOOP_EXTERN_C +#ifdef __cplusplus +#define CLOOP_EXTERN_C extern "C" +#else +#define CLOOP_EXTERN_C +#endif +#endif + + +struct CALC_IDisposable; +struct CALC_IStatus; +struct CALC_IFactory; +struct CALC_ICalculator; +struct CALC_ICalculator2; + + +#define CALC_IDisposable_VERSION 1 + +struct CALC_IDisposable; + +struct CALC_IDisposableVTable +{ + void* cloopDummy[1]; + uintptr_t version; + void (*dispose)(struct CALC_IDisposable* self); +}; + +struct CALC_IDisposable +{ + void* cloopDummy[1]; + struct CALC_IDisposableVTable* vtable; +}; + +CLOOP_EXTERN_C void CALC_IDisposable_dispose(struct CALC_IDisposable* self); + +#define CALC_IStatus_VERSION 3 + +#define CALC_IStatus_ERROR_1 ((int) (1)) +#define CALC_IStatus_ERROR_2 ((int) (2)) +#define CALC_IStatus_ERROR_12 ((int) (CALC_IStatus_ERROR_1 | CALC_IStatus_ERROR_2)) + +struct CALC_IStatus; + +struct CALC_IStatusVTable +{ + void* cloopDummy[1]; + uintptr_t version; + void (*dispose)(struct CALC_IStatus* self); + int (*getCode)(const struct CALC_IStatus* self); + void (*setCode)(struct CALC_IStatus* self, int code); +}; + +struct CALC_IStatus +{ + void* cloopDummy[1]; + struct CALC_IStatusVTable* vtable; +}; + +CLOOP_EXTERN_C void CALC_IStatus_dispose(struct CALC_IStatus* self); +CLOOP_EXTERN_C int CALC_IStatus_getCode(const struct CALC_IStatus* self); +CLOOP_EXTERN_C void CALC_IStatus_setCode(struct CALC_IStatus* self, int code); + +#define CALC_IFactory_VERSION 5 + +struct CALC_IFactory; + +struct CALC_IFactoryVTable +{ + void* cloopDummy[1]; + uintptr_t version; + void (*dispose)(struct CALC_IFactory* self); + struct CALC_IStatus* (*createStatus)(struct CALC_IFactory* self); + struct CALC_ICalculator* (*createCalculator)(struct CALC_IFactory* self, struct CALC_IStatus* status); + struct CALC_ICalculator2* (*createCalculator2)(struct CALC_IFactory* self, struct CALC_IStatus* status); + struct CALC_ICalculator* (*createBrokenCalculator)(struct CALC_IFactory* self, struct CALC_IStatus* status); +}; + +struct CALC_IFactory +{ + void* cloopDummy[1]; + struct CALC_IFactoryVTable* vtable; +}; + +CLOOP_EXTERN_C void CALC_IFactory_dispose(struct CALC_IFactory* self); +CLOOP_EXTERN_C struct CALC_IStatus* CALC_IFactory_createStatus(struct CALC_IFactory* self); +CLOOP_EXTERN_C struct CALC_ICalculator* CALC_IFactory_createCalculator(struct CALC_IFactory* self, struct CALC_IStatus* status); +CLOOP_EXTERN_C struct CALC_ICalculator2* CALC_IFactory_createCalculator2(struct CALC_IFactory* self, struct CALC_IStatus* status); +CLOOP_EXTERN_C struct CALC_ICalculator* CALC_IFactory_createBrokenCalculator(struct CALC_IFactory* self, struct CALC_IStatus* status); + +#define CALC_ICalculator_VERSION 5 + +struct CALC_ICalculator; + +struct CALC_ICalculatorVTable +{ + void* cloopDummy[1]; + uintptr_t version; + void (*dispose)(struct CALC_ICalculator* self); + int (*sum)(const struct CALC_ICalculator* self, struct CALC_IStatus* status, int n1, int n2); + int (*getMemory)(const struct CALC_ICalculator* self); + void (*setMemory)(struct CALC_ICalculator* self, int n); + void (*sumAndStore)(struct CALC_ICalculator* self, struct CALC_IStatus* status, int n1, int n2); +}; + +struct CALC_ICalculator +{ + void* cloopDummy[1]; + struct CALC_ICalculatorVTable* vtable; +}; + +CLOOP_EXTERN_C void CALC_ICalculator_dispose(struct CALC_ICalculator* self); +CLOOP_EXTERN_C int CALC_ICalculator_sum(const struct CALC_ICalculator* self, struct CALC_IStatus* status, int n1, int n2); +CLOOP_EXTERN_C int CALC_ICalculator_getMemory(const struct CALC_ICalculator* self); +CLOOP_EXTERN_C void CALC_ICalculator_setMemory(struct CALC_ICalculator* self, int n); +CLOOP_EXTERN_C void CALC_ICalculator_sumAndStore(struct CALC_ICalculator* self, struct CALC_IStatus* status, int n1, int n2); + +#define CALC_ICalculator2_VERSION 8 + +struct CALC_ICalculator2; + +struct CALC_ICalculator2VTable +{ + void* cloopDummy[1]; + uintptr_t version; + void (*dispose)(struct CALC_ICalculator2* self); + int (*sum)(const struct CALC_ICalculator2* self, struct CALC_IStatus* status, int n1, int n2); + int (*getMemory)(const struct CALC_ICalculator2* self); + void (*setMemory)(struct CALC_ICalculator2* self, int n); + void (*sumAndStore)(struct CALC_ICalculator2* self, struct CALC_IStatus* status, int n1, int n2); + int (*multiply)(const struct CALC_ICalculator2* self, struct CALC_IStatus* status, int n1, int n2); + void (*copyMemory)(struct CALC_ICalculator2* self, const struct CALC_ICalculator* calculator); + void (*copyMemory2)(struct CALC_ICalculator2* self, const int* address); +}; + +struct CALC_ICalculator2 +{ + void* cloopDummy[1]; + struct CALC_ICalculator2VTable* vtable; +}; + +CLOOP_EXTERN_C void CALC_ICalculator2_dispose(struct CALC_ICalculator2* self); +CLOOP_EXTERN_C int CALC_ICalculator2_sum(const struct CALC_ICalculator2* self, struct CALC_IStatus* status, int n1, int n2); +CLOOP_EXTERN_C int CALC_ICalculator2_getMemory(const struct CALC_ICalculator2* self); +CLOOP_EXTERN_C void CALC_ICalculator2_setMemory(struct CALC_ICalculator2* self, int n); +CLOOP_EXTERN_C void CALC_ICalculator2_sumAndStore(struct CALC_ICalculator2* self, struct CALC_IStatus* status, int n1, int n2); +CLOOP_EXTERN_C int CALC_ICalculator2_multiply(const struct CALC_ICalculator2* self, struct CALC_IStatus* status, int n1, int n2); +CLOOP_EXTERN_C void CALC_ICalculator2_copyMemory(struct CALC_ICalculator2* self, const struct CALC_ICalculator* calculator); +CLOOP_EXTERN_C void CALC_ICalculator2_copyMemory2(struct CALC_ICalculator2* self, const int* address); + + +#endif // CALC_C_API_H diff --git a/extern/cloop/src/tests/test1/CalcCppApi.h b/extern/cloop/src/tests/test1/CalcCppApi.h new file mode 100644 index 0000000000..d44cfca88b --- /dev/null +++ b/extern/cloop/src/tests/test1/CalcCppApi.h @@ -0,0 +1,777 @@ +// This file was autogenerated by cloop - Cross Language Object Oriented Programming + +#ifndef CALC_CPP_API_H +#define CALC_CPP_API_H + +#ifndef CLOOP_CARG +#define CLOOP_CARG +#endif + + +namespace calc +{ + class DoNotInherit + { + }; + + template + class Inherit : public T + { + public: + Inherit(DoNotInherit = DoNotInherit()) + : T(DoNotInherit()) + { + } + }; + + // Forward interfaces declarations + + class IDisposable; + class IStatus; + class IFactory; + class ICalculator; + class ICalculator2; + + // Interfaces declarations + + class IDisposable + { + public: + struct VTable + { + void* cloopDummy[1]; + uintptr_t version; + void (CLOOP_CARG *dispose)(IDisposable* self) throw(); + }; + + void* cloopDummy[1]; + VTable* cloopVTable; + + protected: + IDisposable(DoNotInherit) + { + } + + ~IDisposable() + { + } + + public: + static const unsigned VERSION = 1; + + void dispose() + { + static_cast(this->cloopVTable)->dispose(this); + } + }; + + class IStatus : public IDisposable + { + public: + struct VTable : public IDisposable::VTable + { + int (CLOOP_CARG *getCode)(const IStatus* self) throw(); + void (CLOOP_CARG *setCode)(IStatus* self, int code) throw(); + }; + + protected: + IStatus(DoNotInherit) + : IDisposable(DoNotInherit()) + { + } + + ~IStatus() + { + } + + public: + static const unsigned VERSION = 2; + + static const int ERROR_1 = 1; + static const int ERROR_2 = 2; + static const int ERROR_12 = IStatus::ERROR_1 | IStatus::ERROR_2; + + int getCode() const + { + int ret = static_cast(this->cloopVTable)->getCode(this); + return ret; + } + + void setCode(int code) + { + static_cast(this->cloopVTable)->setCode(this, code); + } + }; + + class IFactory : public IDisposable + { + public: + struct VTable : public IDisposable::VTable + { + IStatus* (CLOOP_CARG *createStatus)(IFactory* self) throw(); + ICalculator* (CLOOP_CARG *createCalculator)(IFactory* self, IStatus* status) throw(); + ICalculator2* (CLOOP_CARG *createCalculator2)(IFactory* self, IStatus* status) throw(); + ICalculator* (CLOOP_CARG *createBrokenCalculator)(IFactory* self, IStatus* status) throw(); + }; + + protected: + IFactory(DoNotInherit) + : IDisposable(DoNotInherit()) + { + } + + ~IFactory() + { + } + + public: + static const unsigned VERSION = 2; + + IStatus* createStatus() + { + IStatus* ret = static_cast(this->cloopVTable)->createStatus(this); + return ret; + } + + template ICalculator* createCalculator(StatusType* status) + { + StatusType::clearException(status); + ICalculator* ret = static_cast(this->cloopVTable)->createCalculator(this, status); + StatusType::checkException(status); + return ret; + } + + template ICalculator2* createCalculator2(StatusType* status) + { + StatusType::clearException(status); + ICalculator2* ret = static_cast(this->cloopVTable)->createCalculator2(this, status); + StatusType::checkException(status); + return ret; + } + + template ICalculator* createBrokenCalculator(StatusType* status) + { + StatusType::clearException(status); + ICalculator* ret = static_cast(this->cloopVTable)->createBrokenCalculator(this, status); + StatusType::checkException(status); + return ret; + } + }; + + class ICalculator : public IDisposable + { + public: + struct VTable : public IDisposable::VTable + { + int (CLOOP_CARG *sum)(const ICalculator* self, IStatus* status, int n1, int n2) throw(); + int (CLOOP_CARG *getMemory)(const ICalculator* self) throw(); + void (CLOOP_CARG *setMemory)(ICalculator* self, int n) throw(); + void (CLOOP_CARG *sumAndStore)(ICalculator* self, IStatus* status, int n1, int n2) throw(); + }; + + protected: + ICalculator(DoNotInherit) + : IDisposable(DoNotInherit()) + { + } + + ~ICalculator() + { + } + + public: + static const unsigned VERSION = 4; + + template int sum(StatusType* status, int n1, int n2) const + { + StatusType::clearException(status); + int ret = static_cast(this->cloopVTable)->sum(this, status, n1, n2); + StatusType::checkException(status); + return ret; + } + + int getMemory() const + { + if (cloopVTable->version < 3) + { + return IStatus::ERROR_1; + } + int ret = static_cast(this->cloopVTable)->getMemory(this); + return ret; + } + + void setMemory(int n) + { + if (cloopVTable->version < 3) + { + return; + } + static_cast(this->cloopVTable)->setMemory(this, n); + } + + template void sumAndStore(StatusType* status, int n1, int n2) + { + if (cloopVTable->version < 4) + { + StatusType::setVersionError(status, "ICalculator", cloopVTable->version, 4); + StatusType::checkException(status); + return; + } + StatusType::clearException(status); + static_cast(this->cloopVTable)->sumAndStore(this, status, n1, n2); + StatusType::checkException(status); + } + }; + + class ICalculator2 : public ICalculator + { + public: + struct VTable : public ICalculator::VTable + { + int (CLOOP_CARG *multiply)(const ICalculator2* self, IStatus* status, int n1, int n2) throw(); + void (CLOOP_CARG *copyMemory)(ICalculator2* self, const ICalculator* calculator) throw(); + void (CLOOP_CARG *copyMemory2)(ICalculator2* self, const int* address) throw(); + }; + + protected: + ICalculator2(DoNotInherit) + : ICalculator(DoNotInherit()) + { + } + + ~ICalculator2() + { + } + + public: + static const unsigned VERSION = 6; + + template int multiply(StatusType* status, int n1, int n2) const + { + StatusType::clearException(status); + int ret = static_cast(this->cloopVTable)->multiply(this, status, n1, n2); + StatusType::checkException(status); + return ret; + } + + void copyMemory(const ICalculator* calculator) + { + static_cast(this->cloopVTable)->copyMemory(this, calculator); + } + + void copyMemory2(const int* address) + { + if (cloopVTable->version < 6) + { + return; + } + static_cast(this->cloopVTable)->copyMemory2(this, address); + } + }; + + // Interfaces implementations + + template + class IDisposableBaseImpl : public Base + { + public: + typedef IDisposable Declaration; + + IDisposableBaseImpl(DoNotInherit = DoNotInherit()) + { + static struct VTableImpl : Base::VTable + { + VTableImpl() + { + this->version = Base::VERSION; + this->dispose = &Name::cloopdisposeDispatcher; + } + } vTable; + + this->cloopVTable = &vTable; + } + + static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) throw() + { + try + { + static_cast(self)->Name::dispose(); + } + catch (...) + { + StatusType::catchException(0); + } + } + }; + + template > + class IDisposableImpl : public IDisposableBaseImpl + { + protected: + IDisposableImpl(DoNotInherit = DoNotInherit()) + { + } + + public: + virtual ~IDisposableImpl() + { + } + + virtual void dispose() = 0; + }; + + template + class IStatusBaseImpl : public Base + { + public: + typedef IStatus Declaration; + + IStatusBaseImpl(DoNotInherit = DoNotInherit()) + { + static struct VTableImpl : Base::VTable + { + VTableImpl() + { + this->version = Base::VERSION; + this->dispose = &Name::cloopdisposeDispatcher; + this->getCode = &Name::cloopgetCodeDispatcher; + this->setCode = &Name::cloopsetCodeDispatcher; + } + } vTable; + + this->cloopVTable = &vTable; + } + + static int CLOOP_CARG cloopgetCodeDispatcher(const IStatus* self) throw() + { + try + { + return static_cast(self)->Name::getCode(); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } + + static void CLOOP_CARG cloopsetCodeDispatcher(IStatus* self, int code) throw() + { + try + { + static_cast(self)->Name::setCode(code); + } + catch (...) + { + StatusType::catchException(0); + } + } + + static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) throw() + { + try + { + static_cast(self)->Name::dispose(); + } + catch (...) + { + StatusType::catchException(0); + } + } + }; + + template > > + class IStatusImpl : public IStatusBaseImpl + { + protected: + IStatusImpl(DoNotInherit = DoNotInherit()) + { + } + + public: + virtual ~IStatusImpl() + { + } + + virtual int getCode() const = 0; + virtual void setCode(int code) = 0; + }; + + template + class IFactoryBaseImpl : public Base + { + public: + typedef IFactory Declaration; + + IFactoryBaseImpl(DoNotInherit = DoNotInherit()) + { + static struct VTableImpl : Base::VTable + { + VTableImpl() + { + this->version = Base::VERSION; + this->dispose = &Name::cloopdisposeDispatcher; + this->createStatus = &Name::cloopcreateStatusDispatcher; + this->createCalculator = &Name::cloopcreateCalculatorDispatcher; + this->createCalculator2 = &Name::cloopcreateCalculator2Dispatcher; + this->createBrokenCalculator = &Name::cloopcreateBrokenCalculatorDispatcher; + } + } vTable; + + this->cloopVTable = &vTable; + } + + static IStatus* CLOOP_CARG cloopcreateStatusDispatcher(IFactory* self) throw() + { + try + { + return static_cast(self)->Name::createStatus(); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } + + static ICalculator* CLOOP_CARG cloopcreateCalculatorDispatcher(IFactory* self, IStatus* status) throw() + { + StatusType status2(status); + + try + { + return static_cast(self)->Name::createCalculator(&status2); + } + catch (...) + { + StatusType::catchException(&status2); + return static_cast(0); + } + } + + static ICalculator2* CLOOP_CARG cloopcreateCalculator2Dispatcher(IFactory* self, IStatus* status) throw() + { + StatusType status2(status); + + try + { + return static_cast(self)->Name::createCalculator2(&status2); + } + catch (...) + { + StatusType::catchException(&status2); + return static_cast(0); + } + } + + static ICalculator* CLOOP_CARG cloopcreateBrokenCalculatorDispatcher(IFactory* self, IStatus* status) throw() + { + StatusType status2(status); + + try + { + return static_cast(self)->Name::createBrokenCalculator(&status2); + } + catch (...) + { + StatusType::catchException(&status2); + return static_cast(0); + } + } + + static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) throw() + { + try + { + static_cast(self)->Name::dispose(); + } + catch (...) + { + StatusType::catchException(0); + } + } + }; + + template > > + class IFactoryImpl : public IFactoryBaseImpl + { + protected: + IFactoryImpl(DoNotInherit = DoNotInherit()) + { + } + + public: + virtual ~IFactoryImpl() + { + } + + virtual IStatus* createStatus() = 0; + virtual ICalculator* createCalculator(StatusType* status) = 0; + virtual ICalculator2* createCalculator2(StatusType* status) = 0; + virtual ICalculator* createBrokenCalculator(StatusType* status) = 0; + }; + + template + class ICalculatorBaseImpl : public Base + { + public: + typedef ICalculator Declaration; + + ICalculatorBaseImpl(DoNotInherit = DoNotInherit()) + { + static struct VTableImpl : Base::VTable + { + VTableImpl() + { + this->version = Base::VERSION; + this->dispose = &Name::cloopdisposeDispatcher; + this->sum = &Name::cloopsumDispatcher; + this->getMemory = &Name::cloopgetMemoryDispatcher; + this->setMemory = &Name::cloopsetMemoryDispatcher; + this->sumAndStore = &Name::cloopsumAndStoreDispatcher; + } + } vTable; + + this->cloopVTable = &vTable; + } + + static int CLOOP_CARG cloopsumDispatcher(const ICalculator* self, IStatus* status, int n1, int n2) throw() + { + StatusType status2(status); + + try + { + return static_cast(self)->Name::sum(&status2, n1, n2); + } + catch (...) + { + StatusType::catchException(&status2); + return static_cast(0); + } + } + + static int CLOOP_CARG cloopgetMemoryDispatcher(const ICalculator* self) throw() + { + try + { + return static_cast(self)->Name::getMemory(); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } + + static void CLOOP_CARG cloopsetMemoryDispatcher(ICalculator* self, int n) throw() + { + try + { + static_cast(self)->Name::setMemory(n); + } + catch (...) + { + StatusType::catchException(0); + } + } + + static void CLOOP_CARG cloopsumAndStoreDispatcher(ICalculator* self, IStatus* status, int n1, int n2) throw() + { + StatusType status2(status); + + try + { + static_cast(self)->Name::sumAndStore(&status2, n1, n2); + } + catch (...) + { + StatusType::catchException(&status2); + } + } + + static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) throw() + { + try + { + static_cast(self)->Name::dispose(); + } + catch (...) + { + StatusType::catchException(0); + } + } + }; + + template > > + class ICalculatorImpl : public ICalculatorBaseImpl + { + protected: + ICalculatorImpl(DoNotInherit = DoNotInherit()) + { + } + + public: + virtual ~ICalculatorImpl() + { + } + + virtual int sum(StatusType* status, int n1, int n2) const = 0; + virtual int getMemory() const = 0; + virtual void setMemory(int n) = 0; + virtual void sumAndStore(StatusType* status, int n1, int n2) = 0; + }; + + template + class ICalculator2BaseImpl : public Base + { + public: + typedef ICalculator2 Declaration; + + ICalculator2BaseImpl(DoNotInherit = DoNotInherit()) + { + static struct VTableImpl : Base::VTable + { + VTableImpl() + { + this->version = Base::VERSION; + this->dispose = &Name::cloopdisposeDispatcher; + this->sum = &Name::cloopsumDispatcher; + this->getMemory = &Name::cloopgetMemoryDispatcher; + this->setMemory = &Name::cloopsetMemoryDispatcher; + this->sumAndStore = &Name::cloopsumAndStoreDispatcher; + this->multiply = &Name::cloopmultiplyDispatcher; + this->copyMemory = &Name::cloopcopyMemoryDispatcher; + this->copyMemory2 = &Name::cloopcopyMemory2Dispatcher; + } + } vTable; + + this->cloopVTable = &vTable; + } + + static int CLOOP_CARG cloopmultiplyDispatcher(const ICalculator2* self, IStatus* status, int n1, int n2) throw() + { + StatusType status2(status); + + try + { + return static_cast(self)->Name::multiply(&status2, n1, n2); + } + catch (...) + { + StatusType::catchException(&status2); + return static_cast(0); + } + } + + static void CLOOP_CARG cloopcopyMemoryDispatcher(ICalculator2* self, const ICalculator* calculator) throw() + { + try + { + static_cast(self)->Name::copyMemory(calculator); + } + catch (...) + { + StatusType::catchException(0); + } + } + + static void CLOOP_CARG cloopcopyMemory2Dispatcher(ICalculator2* self, const int* address) throw() + { + try + { + static_cast(self)->Name::copyMemory2(address); + } + catch (...) + { + StatusType::catchException(0); + } + } + + static int CLOOP_CARG cloopsumDispatcher(const ICalculator* self, IStatus* status, int n1, int n2) throw() + { + StatusType status2(status); + + try + { + return static_cast(self)->Name::sum(&status2, n1, n2); + } + catch (...) + { + StatusType::catchException(&status2); + return static_cast(0); + } + } + + static int CLOOP_CARG cloopgetMemoryDispatcher(const ICalculator* self) throw() + { + try + { + return static_cast(self)->Name::getMemory(); + } + catch (...) + { + StatusType::catchException(0); + return static_cast(0); + } + } + + static void CLOOP_CARG cloopsetMemoryDispatcher(ICalculator* self, int n) throw() + { + try + { + static_cast(self)->Name::setMemory(n); + } + catch (...) + { + StatusType::catchException(0); + } + } + + static void CLOOP_CARG cloopsumAndStoreDispatcher(ICalculator* self, IStatus* status, int n1, int n2) throw() + { + StatusType status2(status); + + try + { + static_cast(self)->Name::sumAndStore(&status2, n1, n2); + } + catch (...) + { + StatusType::catchException(&status2); + } + } + + static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) throw() + { + try + { + static_cast(self)->Name::dispose(); + } + catch (...) + { + StatusType::catchException(0); + } + } + }; + + template > > > > + class ICalculator2Impl : public ICalculator2BaseImpl + { + protected: + ICalculator2Impl(DoNotInherit = DoNotInherit()) + { + } + + public: + virtual ~ICalculator2Impl() + { + } + + virtual int multiply(StatusType* status, int n1, int n2) const = 0; + virtual void copyMemory(const ICalculator* calculator) = 0; + virtual void copyMemory2(const int* address) = 0; + }; +}; + + +#endif // CALC_CPP_API_H diff --git a/extern/cloop/src/tests/test1/CalcPascalApi.implementation.pas b/extern/cloop/src/tests/test1/CalcPascalApi.implementation.pas new file mode 100644 index 0000000000..2179609804 --- /dev/null +++ b/extern/cloop/src/tests/test1/CalcPascalApi.implementation.pas @@ -0,0 +1,27 @@ +constructor CalcException.create(code: Integer); +begin + self.code := code; +end; + +function CalcException.getCode: Integer; +begin + Result := code; +end; + +class procedure CalcException.checkException(status: Status); +var + code: Integer; +begin + code := status.getCode(); + + if (code <> 0) then + raise CalcException.create(code); +end; + +class procedure CalcException.catchException(status: Status; e: Exception); +begin + if (e.inheritsFrom(CalcException)) then + status.setCode(CalcException(e).code) + else + status.setCode(-1); +end; diff --git a/extern/cloop/src/tests/test1/CalcPascalApi.interface.pas b/extern/cloop/src/tests/test1/CalcPascalApi.interface.pas new file mode 100644 index 0000000000..2f758aed0f --- /dev/null +++ b/extern/cloop/src/tests/test1/CalcPascalApi.interface.pas @@ -0,0 +1,13 @@ +CalcException = class(Exception) +public + constructor create(code: Integer); + + function getCode: Integer; + + class procedure checkException(status: Status); + class procedure catchException(status: Status; e: Exception); + +private + code: Integer; +end; + diff --git a/extern/cloop/src/tests/test1/CalcPascalApi.pas b/extern/cloop/src/tests/test1/CalcPascalApi.pas new file mode 100644 index 0000000000..62fdfbb238 --- /dev/null +++ b/extern/cloop/src/tests/test1/CalcPascalApi.pas @@ -0,0 +1,559 @@ +{ This file was autogenerated by cloop - Cross Language Object Oriented Programming } + +unit CalcPascalApi; + +interface + +uses Classes, SysUtils; + +type +{$IFNDEF FPC} + QWord = UInt64; +{$ENDIF} + + Disposable = class; + Status = class; + Factory = class; + Calculator = class; + Calculator2 = class; + +CalcException = class(Exception) +public + constructor create(code: Integer); + + function getCode: Integer; + + class procedure checkException(status: Status); + class procedure catchException(status: Status; e: Exception); + +private + code: Integer; +end; + + IntegerPtr = ^Integer; + + Disposable_disposePtr = procedure(this: Disposable); cdecl; + Status_getCodePtr = function(this: Status): Integer; cdecl; + Status_setCodePtr = procedure(this: Status; code: Integer); cdecl; + Factory_createStatusPtr = function(this: Factory): Status; cdecl; + Factory_createCalculatorPtr = function(this: Factory; status: Status): Calculator; cdecl; + Factory_createCalculator2Ptr = function(this: Factory; status: Status): Calculator2; cdecl; + Factory_createBrokenCalculatorPtr = function(this: Factory; status: Status): Calculator; cdecl; + Calculator_sumPtr = function(this: Calculator; status: Status; n1: Integer; n2: Integer): Integer; cdecl; + Calculator_getMemoryPtr = function(this: Calculator): Integer; cdecl; + Calculator_setMemoryPtr = procedure(this: Calculator; n: Integer); cdecl; + Calculator_sumAndStorePtr = procedure(this: Calculator; status: Status; n1: Integer; n2: Integer); cdecl; + Calculator2_multiplyPtr = function(this: Calculator2; status: Status; n1: Integer; n2: Integer): Integer; cdecl; + Calculator2_copyMemoryPtr = procedure(this: Calculator2; calculator: Calculator); cdecl; + Calculator2_copyMemory2Ptr = procedure(this: Calculator2; address: IntegerPtr); cdecl; + + DisposableVTable = class + version: NativeInt; + dispose: Disposable_disposePtr; + end; + + Disposable = class + vTable: DisposableVTable; + + const VERSION = 1; + + procedure dispose(); + end; + + DisposableImpl = class(Disposable) + constructor create; + + procedure dispose(); virtual; abstract; + end; + + StatusVTable = class(DisposableVTable) + getCode: Status_getCodePtr; + setCode: Status_setCodePtr; + end; + + Status = class(Disposable) + const VERSION = 3; + const ERROR_1 = Integer(1); + const ERROR_2 = Integer(2); + const ERROR_12 = Integer(Status.ERROR_1 or Status.ERROR_2); + + function getCode(): Integer; + procedure setCode(code: Integer); + end; + + StatusImpl = class(Status) + constructor create; + + procedure dispose(); virtual; abstract; + function getCode(): Integer; virtual; abstract; + procedure setCode(code: Integer); virtual; abstract; + end; + + FactoryVTable = class(DisposableVTable) + createStatus: Factory_createStatusPtr; + createCalculator: Factory_createCalculatorPtr; + createCalculator2: Factory_createCalculator2Ptr; + createBrokenCalculator: Factory_createBrokenCalculatorPtr; + end; + + Factory = class(Disposable) + const VERSION = 5; + + function createStatus(): Status; + function createCalculator(status: Status): Calculator; + function createCalculator2(status: Status): Calculator2; + function createBrokenCalculator(status: Status): Calculator; + end; + + FactoryImpl = class(Factory) + constructor create; + + procedure dispose(); virtual; abstract; + function createStatus(): Status; virtual; abstract; + function createCalculator(status: Status): Calculator; virtual; abstract; + function createCalculator2(status: Status): Calculator2; virtual; abstract; + function createBrokenCalculator(status: Status): Calculator; virtual; abstract; + end; + + CalculatorVTable = class(DisposableVTable) + sum: Calculator_sumPtr; + getMemory: Calculator_getMemoryPtr; + setMemory: Calculator_setMemoryPtr; + sumAndStore: Calculator_sumAndStorePtr; + end; + + Calculator = class(Disposable) + const VERSION = 5; + + function sum(status: Status; n1: Integer; n2: Integer): Integer; + function getMemory(): Integer; + procedure setMemory(n: Integer); + procedure sumAndStore(status: Status; n1: Integer; n2: Integer); + end; + + CalculatorImpl = class(Calculator) + constructor create; + + procedure dispose(); virtual; abstract; + function sum(status: Status; n1: Integer; n2: Integer): Integer; virtual; abstract; + function getMemory(): Integer; virtual; abstract; + procedure setMemory(n: Integer); virtual; abstract; + procedure sumAndStore(status: Status; n1: Integer; n2: Integer); virtual; abstract; + end; + + Calculator2VTable = class(CalculatorVTable) + multiply: Calculator2_multiplyPtr; + copyMemory: Calculator2_copyMemoryPtr; + copyMemory2: Calculator2_copyMemory2Ptr; + end; + + Calculator2 = class(Calculator) + const VERSION = 8; + + function multiply(status: Status; n1: Integer; n2: Integer): Integer; + procedure copyMemory(calculator: Calculator); + procedure copyMemory2(address: IntegerPtr); + end; + + Calculator2Impl = class(Calculator2) + constructor create; + + procedure dispose(); virtual; abstract; + function sum(status: Status; n1: Integer; n2: Integer): Integer; virtual; abstract; + function getMemory(): Integer; virtual; abstract; + procedure setMemory(n: Integer); virtual; abstract; + procedure sumAndStore(status: Status; n1: Integer; n2: Integer); virtual; abstract; + function multiply(status: Status; n1: Integer; n2: Integer): Integer; virtual; abstract; + procedure copyMemory(calculator: Calculator); virtual; abstract; + procedure copyMemory2(address: IntegerPtr); virtual; abstract; + end; + +implementation + +procedure Disposable.dispose(); +begin + DisposableVTable(vTable).dispose(Self); +end; + +function Status.getCode(): Integer; +begin + Result := StatusVTable(vTable).getCode(Self); +end; + +procedure Status.setCode(code: Integer); +begin + StatusVTable(vTable).setCode(Self, code); +end; + +function Factory.createStatus(): Status; +begin + Result := FactoryVTable(vTable).createStatus(Self); +end; + +function Factory.createCalculator(status: Status): Calculator; +begin + Result := FactoryVTable(vTable).createCalculator(Self, status); + CalcException.checkException(status); +end; + +function Factory.createCalculator2(status: Status): Calculator2; +begin + Result := FactoryVTable(vTable).createCalculator2(Self, status); + CalcException.checkException(status); +end; + +function Factory.createBrokenCalculator(status: Status): Calculator; +begin + Result := FactoryVTable(vTable).createBrokenCalculator(Self, status); + CalcException.checkException(status); +end; + +function Calculator.sum(status: Status; n1: Integer; n2: Integer): Integer; +begin + Result := CalculatorVTable(vTable).sum(Self, status, n1, n2); + CalcException.checkException(status); +end; + +function Calculator.getMemory(): Integer; +begin + Result := CalculatorVTable(vTable).getMemory(Self); +end; + +procedure Calculator.setMemory(n: Integer); +begin + CalculatorVTable(vTable).setMemory(Self, n); +end; + +procedure Calculator.sumAndStore(status: Status; n1: Integer; n2: Integer); +begin + CalculatorVTable(vTable).sumAndStore(Self, status, n1, n2); + CalcException.checkException(status); +end; + +function Calculator2.multiply(status: Status; n1: Integer; n2: Integer): Integer; +begin + Result := Calculator2VTable(vTable).multiply(Self, status, n1, n2); + CalcException.checkException(status); +end; + +procedure Calculator2.copyMemory(calculator: Calculator); +begin + Calculator2VTable(vTable).copyMemory(Self, calculator); +end; + +procedure Calculator2.copyMemory2(address: IntegerPtr); +begin + Calculator2VTable(vTable).copyMemory2(Self, address); +end; + +procedure DisposableImpl_disposeDispatcher(this: Disposable); cdecl; +begin + try + DisposableImpl(this).dispose(); + except + on e: Exception do CalcException.catchException(nil, e); + end +end; + +var + DisposableImpl_vTable: DisposableVTable; + +constructor DisposableImpl.create; +begin + vTable := DisposableImpl_vTable; +end; + +procedure StatusImpl_disposeDispatcher(this: Status); cdecl; +begin + try + StatusImpl(this).dispose(); + except + on e: Exception do CalcException.catchException(nil, e); + end +end; + +function StatusImpl_getCodeDispatcher(this: Status): Integer; cdecl; +begin + try + Result := StatusImpl(this).getCode(); + except + on e: Exception do CalcException.catchException(nil, e); + end +end; + +procedure StatusImpl_setCodeDispatcher(this: Status; code: Integer); cdecl; +begin + try + StatusImpl(this).setCode(code); + except + on e: Exception do CalcException.catchException(nil, e); + end +end; + +var + StatusImpl_vTable: StatusVTable; + +constructor StatusImpl.create; +begin + vTable := StatusImpl_vTable; +end; + +procedure FactoryImpl_disposeDispatcher(this: Factory); cdecl; +begin + try + FactoryImpl(this).dispose(); + except + on e: Exception do CalcException.catchException(nil, e); + end +end; + +function FactoryImpl_createStatusDispatcher(this: Factory): Status; cdecl; +begin + try + Result := FactoryImpl(this).createStatus(); + except + on e: Exception do CalcException.catchException(nil, e); + end +end; + +function FactoryImpl_createCalculatorDispatcher(this: Factory; status: Status): Calculator; cdecl; +begin + try + Result := FactoryImpl(this).createCalculator(status); + except + on e: Exception do CalcException.catchException(status, e); + end +end; + +function FactoryImpl_createCalculator2Dispatcher(this: Factory; status: Status): Calculator2; cdecl; +begin + try + Result := FactoryImpl(this).createCalculator2(status); + except + on e: Exception do CalcException.catchException(status, e); + end +end; + +function FactoryImpl_createBrokenCalculatorDispatcher(this: Factory; status: Status): Calculator; cdecl; +begin + try + Result := FactoryImpl(this).createBrokenCalculator(status); + except + on e: Exception do CalcException.catchException(status, e); + end +end; + +var + FactoryImpl_vTable: FactoryVTable; + +constructor FactoryImpl.create; +begin + vTable := FactoryImpl_vTable; +end; + +procedure CalculatorImpl_disposeDispatcher(this: Calculator); cdecl; +begin + try + CalculatorImpl(this).dispose(); + except + on e: Exception do CalcException.catchException(nil, e); + end +end; + +function CalculatorImpl_sumDispatcher(this: Calculator; status: Status; n1: Integer; n2: Integer): Integer; cdecl; +begin + try + Result := CalculatorImpl(this).sum(status, n1, n2); + except + on e: Exception do CalcException.catchException(status, e); + end +end; + +function CalculatorImpl_getMemoryDispatcher(this: Calculator): Integer; cdecl; +begin + try + Result := CalculatorImpl(this).getMemory(); + except + on e: Exception do CalcException.catchException(nil, e); + end +end; + +procedure CalculatorImpl_setMemoryDispatcher(this: Calculator; n: Integer); cdecl; +begin + try + CalculatorImpl(this).setMemory(n); + except + on e: Exception do CalcException.catchException(nil, e); + end +end; + +procedure CalculatorImpl_sumAndStoreDispatcher(this: Calculator; status: Status; n1: Integer; n2: Integer); cdecl; +begin + try + CalculatorImpl(this).sumAndStore(status, n1, n2); + except + on e: Exception do CalcException.catchException(status, e); + end +end; + +var + CalculatorImpl_vTable: CalculatorVTable; + +constructor CalculatorImpl.create; +begin + vTable := CalculatorImpl_vTable; +end; + +procedure Calculator2Impl_disposeDispatcher(this: Calculator2); cdecl; +begin + try + Calculator2Impl(this).dispose(); + except + on e: Exception do CalcException.catchException(nil, e); + end +end; + +function Calculator2Impl_sumDispatcher(this: Calculator2; status: Status; n1: Integer; n2: Integer): Integer; cdecl; +begin + try + Result := Calculator2Impl(this).sum(status, n1, n2); + except + on e: Exception do CalcException.catchException(status, e); + end +end; + +function Calculator2Impl_getMemoryDispatcher(this: Calculator2): Integer; cdecl; +begin + try + Result := Calculator2Impl(this).getMemory(); + except + on e: Exception do CalcException.catchException(nil, e); + end +end; + +procedure Calculator2Impl_setMemoryDispatcher(this: Calculator2; n: Integer); cdecl; +begin + try + Calculator2Impl(this).setMemory(n); + except + on e: Exception do CalcException.catchException(nil, e); + end +end; + +procedure Calculator2Impl_sumAndStoreDispatcher(this: Calculator2; status: Status; n1: Integer; n2: Integer); cdecl; +begin + try + Calculator2Impl(this).sumAndStore(status, n1, n2); + except + on e: Exception do CalcException.catchException(status, e); + end +end; + +function Calculator2Impl_multiplyDispatcher(this: Calculator2; status: Status; n1: Integer; n2: Integer): Integer; cdecl; +begin + try + Result := Calculator2Impl(this).multiply(status, n1, n2); + except + on e: Exception do CalcException.catchException(status, e); + end +end; + +procedure Calculator2Impl_copyMemoryDispatcher(this: Calculator2; calculator: Calculator); cdecl; +begin + try + Calculator2Impl(this).copyMemory(calculator); + except + on e: Exception do CalcException.catchException(nil, e); + end +end; + +procedure Calculator2Impl_copyMemory2Dispatcher(this: Calculator2; address: IntegerPtr); cdecl; +begin + try + Calculator2Impl(this).copyMemory2(address); + except + on e: Exception do CalcException.catchException(nil, e); + end +end; + +var + Calculator2Impl_vTable: Calculator2VTable; + +constructor Calculator2Impl.create; +begin + vTable := Calculator2Impl_vTable; +end; + +constructor CalcException.create(code: Integer); +begin + self.code := code; +end; + +function CalcException.getCode: Integer; +begin + Result := code; +end; + +class procedure CalcException.checkException(status: Status); +var + code: Integer; +begin + code := status.getCode(); + + if (code <> 0) then + raise CalcException.create(code); +end; + +class procedure CalcException.catchException(status: Status; e: Exception); +begin + if (e.inheritsFrom(CalcException)) then + status.setCode(CalcException(e).code) + else + status.setCode(-1); +end; +initialization + DisposableImpl_vTable := DisposableVTable.create; + DisposableImpl_vTable.version := 1; + DisposableImpl_vTable.dispose := @DisposableImpl_disposeDispatcher; + + StatusImpl_vTable := StatusVTable.create; + StatusImpl_vTable.version := 3; + StatusImpl_vTable.dispose := @StatusImpl_disposeDispatcher; + StatusImpl_vTable.getCode := @StatusImpl_getCodeDispatcher; + StatusImpl_vTable.setCode := @StatusImpl_setCodeDispatcher; + + FactoryImpl_vTable := FactoryVTable.create; + FactoryImpl_vTable.version := 5; + FactoryImpl_vTable.dispose := @FactoryImpl_disposeDispatcher; + FactoryImpl_vTable.createStatus := @FactoryImpl_createStatusDispatcher; + FactoryImpl_vTable.createCalculator := @FactoryImpl_createCalculatorDispatcher; + FactoryImpl_vTable.createCalculator2 := @FactoryImpl_createCalculator2Dispatcher; + FactoryImpl_vTable.createBrokenCalculator := @FactoryImpl_createBrokenCalculatorDispatcher; + + CalculatorImpl_vTable := CalculatorVTable.create; + CalculatorImpl_vTable.version := 5; + CalculatorImpl_vTable.dispose := @CalculatorImpl_disposeDispatcher; + CalculatorImpl_vTable.sum := @CalculatorImpl_sumDispatcher; + CalculatorImpl_vTable.getMemory := @CalculatorImpl_getMemoryDispatcher; + CalculatorImpl_vTable.setMemory := @CalculatorImpl_setMemoryDispatcher; + CalculatorImpl_vTable.sumAndStore := @CalculatorImpl_sumAndStoreDispatcher; + + Calculator2Impl_vTable := Calculator2VTable.create; + Calculator2Impl_vTable.version := 8; + Calculator2Impl_vTable.dispose := @Calculator2Impl_disposeDispatcher; + Calculator2Impl_vTable.sum := @Calculator2Impl_sumDispatcher; + Calculator2Impl_vTable.getMemory := @Calculator2Impl_getMemoryDispatcher; + Calculator2Impl_vTable.setMemory := @Calculator2Impl_setMemoryDispatcher; + Calculator2Impl_vTable.sumAndStore := @Calculator2Impl_sumAndStoreDispatcher; + Calculator2Impl_vTable.multiply := @Calculator2Impl_multiplyDispatcher; + Calculator2Impl_vTable.copyMemory := @Calculator2Impl_copyMemoryDispatcher; + Calculator2Impl_vTable.copyMemory2 := @Calculator2Impl_copyMemory2Dispatcher; + +finalization + DisposableImpl_vTable.destroy; + StatusImpl_vTable.destroy; + FactoryImpl_vTable.destroy; + CalculatorImpl_vTable.destroy; + Calculator2Impl_vTable.destroy; + +end. diff --git a/extern/cloop/src/tests/test1/CppTest.cpp b/extern/cloop/src/tests/test1/CppTest.cpp new file mode 100644 index 0000000000..b8c6fbb70e --- /dev/null +++ b/extern/cloop/src/tests/test1/CppTest.cpp @@ -0,0 +1,432 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Adriano dos Santos Fernandes. + * + * Copyright (c) 2014 Adriano dos Santos Fernandes + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + */ + +#include +#include "CalcCppApi.h" +#include +#include + +#ifdef WIN32 +#include +#define DLL_EXPORT __declspec(dllexport) +#else +#include +#define DLL_EXPORT +#endif + + +//-------------------------------------- + +// CalcException + + +class CalcException +{ +public: + CalcException(calc::IStatus* status) + : code(status ? status->getCode() : -1) + { + } + + CalcException(int code) + : code(code) + { + } + +public: + int code; +}; + + +//-------------------------------------- + +// StatusWrapper + + +class StatusWrapper : public calc::IStatusImpl +{ +public: + StatusWrapper(calc::IStatus* delegate) + : delegate(delegate), + code(0) + { + } + + virtual void dispose() + { + delete this; + } + + virtual int getCode() const + { + return code; + } + + virtual void setCode(int code) + { + this->code = code; + delegate->setCode(code); + } + + static void clearException(StatusWrapper* status) + { + if (status->code != 0) + status->setCode(0); + } + + static void checkException(StatusWrapper* status) + { + if (status->code != 0) + throw CalcException(status); + } + + static void catchException(StatusWrapper* status) + { + try + { + throw; + } + catch (const CalcException& e) + { + assert(status); + status->setCode(e.code); + } + catch (...) + { + assert(false); + } + } + + static void setVersionError(StatusWrapper* status, const char* /*interfaceName*/, + unsigned /*currentVersion*/, unsigned /*expectedVersion*/) + { + status->setCode(calc::IStatus::ERROR_1); + } + +private: + calc::IStatus* delegate; + int code; +}; + + +//-------------------------------------- + +// StatusImpl + + +class StatusImpl : public calc::IStatusImpl +{ +public: + StatusImpl() + : code(0) + { + } + + virtual void dispose() + { + delete this; + } + + virtual int getCode() const + { + return code; + } + + virtual void setCode(int code) + { + this->code = code; + } + +private: + int code; +}; + + +//-------------------------------------- + +// CalculatorImpl + + +class CalculatorImpl : public calc::ICalculatorImpl +{ +public: + CalculatorImpl() + : memory(0) + { + } + + virtual void dispose() + { + delete this; + } + + virtual int sum(StatusWrapper* status, int n1, int n2) const + { + if (n1 + n2 > 1000) + throw CalcException(calc::IStatus::ERROR_1); + else + return n1 + n2; + } + + virtual int getMemory() const + { + return memory; + } + + virtual void setMemory(int n) + { + memory = n; + } + + virtual void sumAndStore(StatusWrapper* status, int n1, int n2) + { + setMemory(sum(status, n1, n2)); + } + +private: + int memory; +}; + + +//-------------------------------------- + +// Calculator2Impl + + +class Calculator2Impl : public calc::ICalculator2Impl +{ +public: + Calculator2Impl() + : memory(0) + { + } + + virtual void dispose() + { + delete this; + } + + virtual int sum(StatusWrapper* status, int n1, int n2) const + { + if (n1 + n2 > 1000) + throw CalcException(calc::IStatus::ERROR_1); + else + return n1 + n2; + } + + virtual int getMemory() const + { + return memory; + } + + virtual void setMemory(int n) + { + memory = n; + } + + virtual void sumAndStore(StatusWrapper* status, int n1, int n2) + { + setMemory(sum(status, n1, n2)); + } + + virtual int multiply(StatusWrapper* status, int n1, int n2) const + { + return n1 * n2; + } + + virtual void copyMemory(const calc::ICalculator* calculator) + { + setMemory(calculator->getMemory()); + } + + virtual void copyMemory2(const int* address) + { + setMemory(*address); + } + +private: + int memory; +}; + + +//-------------------------------------- + +// BrokenCalculatorImpl + + +class BrokenCalculatorImpl : + public calc::ICalculatorBaseImpl +{ +public: + virtual int sum(StatusWrapper* status, int n1, int n2) const + { + return CalculatorImpl::sum(status, n1, n2) + 1; + } +}; + + +//-------------------------------------- + +// FactoryImpl + + +class FactoryImpl : public calc::IFactoryImpl +{ +public: + virtual void dispose() + { + delete this; + } + + virtual calc::IStatus* createStatus() + { + return new StatusImpl(); + } + + virtual calc::ICalculator* createCalculator(StatusWrapper* /*status*/) + { + return new CalculatorImpl(); + } + + virtual calc::ICalculator2* createCalculator2(StatusWrapper* /*status*/) + { + return new Calculator2Impl(); + } + + virtual calc::ICalculator* createBrokenCalculator(StatusWrapper* /*status*/) + { + return new BrokenCalculatorImpl(); + } +}; + + +//-------------------------------------- + +// Library entry point + + +extern "C" DLL_EXPORT calc::IFactory* createFactory() +{ + return new FactoryImpl(); +} + + +//-------------------------------------- + + +static void test(calc::IFactory* (*createFactory)()) +{ + calc::IFactory* factory = createFactory(); + StatusImpl statusImpl; + StatusWrapper status(&statusImpl); + + calc::ICalculator* calculator = factory->createCalculator(&status); + + calculator->sumAndStore(&status, 1, 22); + printf("%d\n", calculator->getMemory()); // 23 + + calculator->setMemory(calculator->sum(&status, 2, 33)); + printf("%d\n", calculator->getMemory()); // 35 + + calc::ICalculator2* calculator2 = factory->createCalculator2(&status); + + calculator2->copyMemory(calculator); + printf("%d\n", calculator2->getMemory()); // 35 + + int address = 40; + calculator2->copyMemory2(&address); + printf("%d\n", calculator2->getMemory()); // 40 + + calculator->dispose(); + calculator = calculator2; + + calculator->sumAndStore(&status, 1, 22); + printf("%d\n", calculator->getMemory()); // 23 + + calculator->setMemory(calculator->sum(&status, 2, 33)); + printf("%d\n", calculator->getMemory()); // 35 + + calculator2->sumAndStore(&status, 1, 22); + printf("%d\n", calculator2->getMemory()); // 23 + + calculator2->setMemory(calculator2->multiply(&status, 2, 33)); + printf("%d\n", calculator2->getMemory()); // 66 + + calculator->dispose(); + + calculator = factory->createBrokenCalculator(&status); + + calculator->sumAndStore(&status, 1, 22); + printf("%d\n", calculator->getMemory()); // 24 + + calculator->setMemory(calculator->sum(&status, 2, 33)); + printf("%d\n", calculator->getMemory()); // 36 + + try + { + printf("%d\n", calculator->sum(&status, 600, 600)); + } + catch (const CalcException& e) + { + printf("exception %d\n", e.code); // exception 1 + } + + calculator->dispose(); + factory->dispose(); + + printf("\n"); +} + +#ifdef WIN32 +template +static void loadSymbol(HMODULE library, const char* name, T& symbol) +{ + symbol = (T) GetProcAddress(library, name); +} +#else +template +static void loadSymbol(void* library, const char* name, T& symbol) +{ + symbol = (T) dlsym(library, name); +} +#endif + +int main(int argc, char* argv[]) +{ + calc::IFactory* (*createFactory)(); + +#ifdef WIN32 + HMODULE library = LoadLibrary(argv[1]); +#else + void* library = dlopen(argv[1], RTLD_LAZY); +#endif + + loadSymbol(library, "createFactory", createFactory); + test(createFactory); + +#ifdef WIN32 + FreeLibrary(library); +#else + dlclose(library); +#endif + + return 0; +} diff --git a/extern/cloop/src/tests/test1/Interface.idl b/extern/cloop/src/tests/test1/Interface.idl new file mode 100644 index 0000000000..eda94f6ede --- /dev/null +++ b/extern/cloop/src/tests/test1/Interface.idl @@ -0,0 +1,69 @@ +/* + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Adriano dos Santos Fernandes. + * + * Copyright (c) 2014 Adriano dos Santos Fernandes + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + */ + +//// TODO: test structs + +// Base for all interfaces. +interface Disposable +{ + void dispose(); +} + +/* Status is the *exception* class. */ +[exception] +interface Status : Disposable +{ + const int ERROR_1 = 1; + const int ERROR_2 = 0x2; + const int ERROR_12 = ERROR_1 | ERROR_2; + + int getCode() const; + void setCode(int code); +} + +interface Factory : Disposable +{ + Status createStatus(); + Calculator createCalculator(Status status); + Calculator2 createCalculator2(Status status); + Calculator createBrokenCalculator(Status status); +} + +interface Calculator : Disposable +{ + int sum(Status status, int n1, int n2) const; + +version: + [notImplemented(Status::ERROR_1)] int getMemory() const; + void setMemory(int n); + +version: + void sumAndStore(Status status, int n1, int n2); +} + +interface Calculator2 : Calculator +{ + int multiply(Status status, int n1, int n2) const; + void copyMemory(const Calculator calculator); + +version: + void copyMemory2(const int* address); +} diff --git a/extern/cloop/src/tests/test1/PascalClasses.pas b/extern/cloop/src/tests/test1/PascalClasses.pas new file mode 100644 index 0000000000..806196c16d --- /dev/null +++ b/extern/cloop/src/tests/test1/PascalClasses.pas @@ -0,0 +1,247 @@ +{ + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Adriano dos Santos Fernandes. + * + * Copyright (c) 2014 Adriano dos Santos Fernandes + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. +} + +unit PascalClasses; + +interface + +uses CalcPascalApi; + +type + MyStatusImpl = class(StatusImpl) + constructor create; + + procedure dispose(); override; + function getCode(): Integer; override; + procedure setCode(n: Integer); override; + + private + code: Integer; + end; + + MyCalculatorImpl = class(CalculatorImpl) + constructor create; + + procedure dispose(); override; + function sum(status: Status; n1: Integer; n2: Integer): Integer; override; + function getMemory(): Integer; override; + procedure setMemory(n: Integer); override; + procedure sumAndStore(status: Status; n1: Integer; n2: Integer); override; + + private + memory: Integer; + end; + + MyCalculator2Impl = class(Calculator2Impl) + constructor create; + + procedure dispose(); override; + function sum(status: Status; n1: Integer; n2: Integer): Integer; override; + function getMemory(): Integer; override; + procedure setMemory(n: Integer); override; + procedure sumAndStore(status: Status; n1: Integer; n2: Integer); override; + function multiply(status: Status; n1: Integer; n2: Integer): Integer; override; + procedure copyMemory(calculator: Calculator); override; + procedure copyMemory2(address: IntegerPtr); override; + + private + memory: Integer; + end; + + MyBrokenCalculatorImpl = class(MyCalculatorImpl) + function sum(status: Status; n1: Integer; n2: Integer): Integer; override; + end; + + MyFactoryImpl = class(FactoryImpl) + procedure dispose(); override; + function createStatus(): Status; override; + function createCalculator(status: Status): Calculator; override; + function createCalculator2(status: Status): Calculator2; override; + function createBrokenCalculator(status: Status): Calculator; override; + end; + +implementation + +//-------------------------------------- + +// MyStatusImpl + + +constructor MyStatusImpl.create; +begin + inherited; + code := 0; +end; + +procedure MyStatusImpl.dispose(); +begin + self.destroy(); +end; + +function MyStatusImpl.getCode(): Integer; +begin + Result := code; +end; + +procedure MyStatusImpl.setCode(n: Integer); +begin + code := n; +end; + + +//-------------------------------------- + +// MyCalculatorImpl + + +constructor MyCalculatorImpl.create; +begin + inherited; + memory := 0; +end; + +procedure MyCalculatorImpl.dispose(); +begin + self.destroy(); +end; + +function MyCalculatorImpl.sum(status: Status; n1: Integer; n2: Integer): Integer; +begin + if (n1 + n2 > 1000) then + raise CalcException.create(Status.ERROR_1) + else + Result := n1 + n2; +end; + +function MyCalculatorImpl.getMemory(): Integer; +begin + Result := memory; +end; + +procedure MyCalculatorImpl.setMemory(n: Integer); +begin + memory := n; +end; + +procedure MyCalculatorImpl.sumAndStore(status: Status; n1: Integer; n2: Integer); +begin + setMemory(sum(status, n1, n2)); +end; + + +//-------------------------------------- + +// MyCalculator2Impl + + +constructor MyCalculator2Impl.create; +begin + inherited; + memory := 0; +end; + +procedure MyCalculator2Impl.dispose(); +begin + self.destroy(); +end; + +function MyCalculator2Impl.sum(status: Status; n1: Integer; n2: Integer): Integer; +begin + if (n1 + n2 > 1000) then + raise CalcException.create(Status.ERROR_1) + else + Result := n1 + n2; +end; + +function MyCalculator2Impl.getMemory(): Integer; +begin + Result := memory; +end; + +procedure MyCalculator2Impl.setMemory(n: Integer); +begin + memory := n; +end; + +procedure MyCalculator2Impl.sumAndStore(status: Status; n1: Integer; n2: Integer); +begin + setMemory(sum(status, n1, n2)); +end; + +function MyCalculator2Impl.multiply(status: Status; n1: Integer; n2: Integer): Integer; +begin + Result := n1 * n2; +end; + +procedure MyCalculator2Impl.copyMemory(calculator: Calculator); +begin + setMemory(calculator.getMemory()); +end; + +procedure MyCalculator2Impl.copyMemory2(address: IntegerPtr); +begin + setMemory(address^); +end; + + +//-------------------------------------- + +// MyBrokenCalculatorImpl + + +function MyBrokenCalculatorImpl.sum(status: Status; n1: Integer; n2: Integer): Integer; +begin + Result := inherited sum(status, n1, n2) + 1; +end; + + +//-------------------------------------- + +// MyFactoryImpl + + +procedure MyFactoryImpl.dispose(); +begin + self.destroy(); +end; + +function MyFactoryImpl.createStatus(): Status; +begin + Result := MyStatusImpl.create; +end; + +function MyFactoryImpl.createCalculator(status: Status): Calculator; +begin + Result := MyCalculatorImpl.create; +end; + +function MyFactoryImpl.createCalculator2(status: Status): Calculator2; +begin + Result := MyCalculator2Impl.create; +end; + +function MyFactoryImpl.createBrokenCalculator(status: Status): Calculator; +begin + Result := MyBrokenCalculatorImpl.create; +end; + + +end. diff --git a/extern/cloop/src/tests/test1/PascalLibrary.dpr b/extern/cloop/src/tests/test1/PascalLibrary.dpr new file mode 100644 index 0000000000..02142a3b89 --- /dev/null +++ b/extern/cloop/src/tests/test1/PascalLibrary.dpr @@ -0,0 +1,40 @@ +{ + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Adriano dos Santos Fernandes. + * + * Copyright (c) 2014 Adriano dos Santos Fernandes + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. +} + +library PascalLibrary; + +uses CalcPascalApi, PascalClasses; + + +//-------------------------------------- + +// Library entry point + + +function createFactory: Factory; cdecl; +begin + Result := MyFactoryImpl.create(); +end; + +exports + createFactory; + +end. diff --git a/extern/cloop/src/tests/test1/PascalTest.dpr b/extern/cloop/src/tests/test1/PascalTest.dpr new file mode 100644 index 0000000000..779b62adea --- /dev/null +++ b/extern/cloop/src/tests/test1/PascalTest.dpr @@ -0,0 +1,126 @@ +{ + * The contents of this file are subject to the Initial + * Developer's Public License Version 1.0 (the "License"); + * you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. + * + * Software distributed under the License is distributed AS IS, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. + * See the License for the specific language governing rights + * and limitations under the License. + * + * The Original Code was created by Adriano dos Santos Fernandes. + * + * Copyright (c) 2014 Adriano dos Santos Fernandes + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. +} + +program PascalTest; + +{$ifndef FPC} +{$APPTYPE CONSOLE} +{$endif} + +uses CalcPascalApi, PascalClasses, +{$ifndef FPC} + System.SysUtils, Windows; +{$else} + SysUtils, DynLibs; +{$endif} + +type + CreateFactoryPtr = function(): Factory; cdecl; + +var +{$ifndef FPC} + lib: THandle; +{$else} + lib: TLibHandle; +{$endif} + createFactory: CreateFactoryPtr; + fact: Factory; + stat: Status; + calc: Calculator; + calc2: Calculator2; + address: Integer; +begin +{$ifndef FPC} + lib := LoadLibrary(PWideChar(ParamStr(1))); +{$else} + lib := LoadLibrary(ParamStr(1)); +{$endif} + +{$ifndef FPC} + createFactory := GetProcAddress(lib, 'createFactory'); +{$else} + createFactory := GetProcedureAddress(lib, 'createFactory'); +{$endif} + + fact := createFactory(); + stat := MyStatusImpl.create; + + calc := fact.createCalculator(stat); + + calc.sumAndStore(stat, 1, 22); + WriteLn(calc.getMemory()); // 23 + + calc.setMemory(calc.sum(stat, 2, 33)); + WriteLn(calc.getMemory()); // 35 + + calc2 := fact.createCalculator2(stat); + + calc2.copyMemory(calc); + WriteLn(calc2.getMemory()); // 35 + + address := 40; + calc2.copyMemory2(@address); + WriteLn(calc2.getMemory()); // 35 + + calc.dispose(); + calc := calc2; + + calc.sumAndStore(stat, 1, 22); + WriteLn(calc.getMemory()); // 23 + + calc.setMemory(calc.sum(stat, 2, 33)); + WriteLn(calc.getMemory()); // 35 + + calc2.sumAndStore(stat, 1, 22); + WriteLn(calc2.getMemory()); // 23 + + calc2.setMemory(calc2.multiply(stat, 2, 33)); + WriteLn(calc2.getMemory()); // 66 + + calc.dispose(); + + calc := fact.createBrokenCalculator(stat); + + calc.sumAndStore(stat, 1, 22); + WriteLn(calc.getMemory()); // 24 + + calc.setMemory(calc.sum(stat, 2, 33)); + WriteLn(calc.getMemory()); // 36 + + try + WriteLn(calc.sum(stat, 600, 600)); + except + on e: CalcException do + WriteLn('exception ', e.getCode()); // exception 1 + end; + + calc.dispose(); + stat.dispose(); + fact.dispose(); + + WriteLn; + +{$ifndef FPC} + FreeLibrary(lib); +{$else} + UnloadLibrary(lib); +{$endif} +end. diff --git a/extern/cloop/src/tests/test1/test1-c-dll.vcxproj b/extern/cloop/src/tests/test1/test1-c-dll.vcxproj new file mode 100644 index 0000000000..d1ae5e48cf --- /dev/null +++ b/extern/cloop/src/tests/test1/test1-c-dll.vcxproj @@ -0,0 +1,156 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + Win32Proj + test1-c-dll + + + + DynamicLibrary + true + NotSet + + + DynamicLibrary + true + NotSet + + + DynamicLibrary + false + NotSet + + + DynamicLibrary + false + NotSet + + + + + + + + + + + + + + + + + + + true + test1-c-dll + $(SolutionDir)\output\$(Configuration)\bin\ + $(SolutionDir)\build\$(Configuration)\$(ProjectName)\ + + + true + test1-c-dll + $(SolutionDir)\output\$(Configuration)\bin\ + $(SolutionDir)\build\$(Configuration)\$(ProjectName)\ + + + true + test1-c-dll + $(SolutionDir)\output\$(Configuration)\bin\ + $(SolutionDir)\build\$(Configuration)\$(ProjectName)\ + + + true + test1-c-dll + $(SolutionDir)\output\$(Configuration)\bin\ + $(SolutionDir)\build\$(Configuration)\$(ProjectName)\ + + + + WIN32;_DEBUG;_WINDOWS;_USRDLL;TEST1_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + + + MachineX86 + true + Windows + $(OutDir)$(TargetName)$(TargetExt) + + + + + WIN32;_DEBUG;_WINDOWS;_USRDLL;TEST1_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + + + true + Windows + $(OutDir)$(TargetName)$(TargetExt) + + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;TEST1_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + MachineX86 + true + Windows + true + true + $(OutDir)$(TargetName)$(TargetExt) + + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;TEST1_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + true + Windows + true + true + $(OutDir)$(TargetName)$(TargetExt) + + + + + + + + + + + + + \ No newline at end of file diff --git a/extern/cloop/src/tests/test1/test1-c-dll.vcxproj.filters b/extern/cloop/src/tests/test1/test1-c-dll.vcxproj.filters new file mode 100644 index 0000000000..180eab0a45 --- /dev/null +++ b/extern/cloop/src/tests/test1/test1-c-dll.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Source Files + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/extern/cloop/src/tests/test1/test1-c-exe.vcxproj b/extern/cloop/src/tests/test1/test1-c-exe.vcxproj new file mode 100644 index 0000000000..01ba2892ae --- /dev/null +++ b/extern/cloop/src/tests/test1/test1-c-exe.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + {4495AE41-C12E-446C-AE2F-5CECF5F80B17} + Win32Proj + test1cexe + + + + Application + true + NotSet + + + Application + true + NotSet + + + Application + false + true + NotSet + + + Application + false + true + NotSet + + + + + + + + + + + + + + + + + + + true + test1-c-exe + $(SolutionDir)\output\$(Configuration)\bin\ + $(SolutionDir)\build\$(Configuration)\$(ProjectName)\ + + + true + test1-c-exe + $(SolutionDir)\output\$(Configuration)\bin\ + $(SolutionDir)\build\$(Configuration)\$(ProjectName)\ + + + false + test1-c-exe + $(SolutionDir)\output\$(Configuration)\bin\ + $(SolutionDir)\build\$(Configuration)\$(ProjectName)\ + + + false + test1-c-exe + $(SolutionDir)\output\$(Configuration)\bin\ + $(SolutionDir)\build\$(Configuration)\$(ProjectName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + \ No newline at end of file diff --git a/extern/cloop/src/tests/test1/test1-c-exe.vcxproj.filters b/extern/cloop/src/tests/test1/test1-c-exe.vcxproj.filters new file mode 100644 index 0000000000..6fa207554b --- /dev/null +++ b/extern/cloop/src/tests/test1/test1-c-exe.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/extern/cloop/src/tests/test1/test1-cpp-dll.vcxproj b/extern/cloop/src/tests/test1/test1-cpp-dll.vcxproj new file mode 100644 index 0000000000..a718512cc1 --- /dev/null +++ b/extern/cloop/src/tests/test1/test1-cpp-dll.vcxproj @@ -0,0 +1,155 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + Win32Proj + test1-cpp-dll + + + + DynamicLibrary + true + NotSet + + + DynamicLibrary + true + NotSet + + + DynamicLibrary + false + NotSet + + + DynamicLibrary + false + NotSet + + + + + + + + + + + + + + + + + + + true + test1-cpp-dll + $(SolutionDir)\output\$(Configuration)\bin\ + $(SolutionDir)\build\$(Configuration)\$(ProjectName)\ + + + true + test1-cpp-dll + $(SolutionDir)\output\$(Configuration)\bin\ + $(SolutionDir)\build\$(Configuration)\$(ProjectName)\ + + + true + test1-cpp-dll + $(SolutionDir)\output\$(Configuration)\bin\ + $(SolutionDir)\build\$(Configuration)\$(ProjectName)\ + + + true + test1-cpp-dll + $(SolutionDir)\output\$(Configuration)\bin\ + $(SolutionDir)\build\$(Configuration)\$(ProjectName)\ + + + + WIN32;_DEBUG;_WINDOWS;_USRDLL;TEST1_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + + + MachineX86 + true + Windows + $(OutDir)$(TargetName)$(TargetExt) + + + + + WIN32;_DEBUG;_WINDOWS;_USRDLL;TEST1_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + + + true + Windows + $(OutDir)$(TargetName)$(TargetExt) + + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;TEST1_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + MachineX86 + true + Windows + true + true + $(OutDir)$(TargetName)$(TargetExt) + + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;TEST1_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + true + Windows + true + true + $(OutDir)$(TargetName)$(TargetExt) + + + + + + + + + + + + \ No newline at end of file diff --git a/extern/cloop/src/tests/test1/test1-cpp-dll.vcxproj.filters b/extern/cloop/src/tests/test1/test1-cpp-dll.vcxproj.filters new file mode 100644 index 0000000000..e8a652d7cc --- /dev/null +++ b/extern/cloop/src/tests/test1/test1-cpp-dll.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/extern/cloop/src/tests/test1/test1-cpp-exe.vcxproj b/extern/cloop/src/tests/test1/test1-cpp-exe.vcxproj new file mode 100644 index 0000000000..bc2b7dff8d --- /dev/null +++ b/extern/cloop/src/tests/test1/test1-cpp-exe.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {096EBD8E-C0FC-4286-A01D-89D562F3AE12} + Win32Proj + test1cppexe + + + + Application + true + NotSet + + + Application + true + NotSet + + + Application + false + true + NotSet + + + Application + false + true + NotSet + + + + + + + + + + + + + + + + + + + true + test1-cpp-exe + $(SolutionDir)\output\$(Configuration)\bin\ + $(SolutionDir)\build\$(Configuration)\$(ProjectName)\ + + + true + test1-cpp-exe + $(SolutionDir)\output\$(Configuration)\bin\ + $(SolutionDir)\build\$(Configuration)\$(ProjectName)\ + + + false + test1-cpp-exe + $(SolutionDir)\output\$(Configuration)\bin\ + $(SolutionDir)\build\$(Configuration)\$(ProjectName)\ + + + false + test1-cpp-exe + $(SolutionDir)\output\$(Configuration)\bin\ + $(SolutionDir)\build\$(Configuration)\$(ProjectName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + true + + + + + + + + + + + + \ No newline at end of file diff --git a/extern/cloop/src/tests/test1/test1-cpp-exe.vcxproj.filters b/extern/cloop/src/tests/test1/test1-cpp-exe.vcxproj.filters new file mode 100644 index 0000000000..2fe9836743 --- /dev/null +++ b/extern/cloop/src/tests/test1/test1-cpp-exe.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file