diff --git a/recipes/lemon/all/CMakeLists.txt b/recipes/lemon/all/CMakeLists.txt new file mode 100644 index 0000000000000..4492f0ecd9346 --- /dev/null +++ b/recipes/lemon/all/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 2.8.14) +project(ConanLemon C) + +include(conanbuildinfo.cmake) +conan_basic_setup() + +add_executable(lemon source_subfolder/tool/lemon.c) +install(TARGETS lemon RUNTIME DESTINATION bin) +install(FILES source_subfolder/tool/lempar.c DESTINATION bin) diff --git a/recipes/lemon/all/conandata.yml b/recipes/lemon/all/conandata.yml new file mode 100644 index 0000000000000..9614c3e605634 --- /dev/null +++ b/recipes/lemon/all/conandata.yml @@ -0,0 +1,8 @@ +sources: + "3.32.3": + "url": "https://sqlite.org/2020/sqlite-src-3320300.zip" + "sha256": "9312f0865d3692384d466048f746d18f88e7ffd1758b77d4f07904e03ed5f5b9" +patches: + "3.32.3": + - patch_file: "patches/0001-use-executable-template-path.patch" + base_path: "source_subfolder" diff --git a/recipes/lemon/all/conanfile.py b/recipes/lemon/all/conanfile.py new file mode 100644 index 0000000000000..0f7ae9388b6a8 --- /dev/null +++ b/recipes/lemon/all/conanfile.py @@ -0,0 +1,58 @@ +import os +from conans import CMake, ConanFile, tools + + +class LemonConan(ConanFile): + name = "lemon" + description = "The Lemon program reads a grammar of the input language and emits C-code to implement a parser for that language." + url = "https://github.com/conan-io/conan-center-index" + homepage = "https://sqlite.org/lemon.html" + topics = ("conan", "lemon", "grammar", "lexer", "lalr", "parser", "generator", "sqlite") + license = "Public Domain" + exports_sources = "CMakeLists.txt", "patches/**" + settings = "os", "compiler", "arch", "build_type" + generators = "cmake" + + @property + def _source_subfolder(self): + return "source_subfolder" + + _cmake = None + + def configure(self): + del self.settings.compiler.libcxx + del self.settings.compiler.cppstd + + def source(self): + tools.get(**self.conan_data["sources"][self.version]) + url = self.conan_data["sources"][self.version]["url"] + archive_name = os.path.basename(url) + archive_name = os.path.splitext(archive_name)[0] + os.rename(archive_name, self._source_subfolder) + + def _configure_cmake(self): + if self._cmake: + return self._cmake + self._cmake = CMake(self) + self._cmake.configure() + return self._cmake + + def build(self): + for patch in self.conan_data.get("patches", {}).get(self.version, []): + tools.patch(**patch) + cmake = self._configure_cmake() + cmake.build() + + def _extract_license_text(self): + header = tools.load(os.path.join(self._source_subfolder, "tool", "lempar.c")) + return "\n".join(line.strip(" \n*") for line in header[3:header.find("*******", 1)].splitlines()) + + def package(self): + tools.save(os.path.join(self.package_folder, "licenses", "LICENSE"), self._extract_license_text()) + cmake = self._configure_cmake() + cmake.install() + + def package_info(self): + bin_path = os.path.join(self.package_folder, "bin") + self.output.info("Appending PATH environment variable: {}".format(bin_path)) + self.env_info.PATH.append(bin_path) diff --git a/recipes/lemon/all/patches/0001-use-executable-template-path.patch b/recipes/lemon/all/patches/0001-use-executable-template-path.patch new file mode 100644 index 0000000000000..031dc360a18b7 --- /dev/null +++ b/recipes/lemon/all/patches/0001-use-executable-template-path.patch @@ -0,0 +1,65 @@ +--- tool/lemon.c ++++ tool/lemon.c +@@ -3502,11 +3502,53 @@ + } + } + ++#ifdef _WIN32 ++# define WIN32_LEAN_AND_MEAN ++# include ++#else ++# include ++# include ++#endif ++#include ++ ++#define DEFAULT_PATH "." ++ ++static char *get_default_template_path(const char *filename) { ++ static char static_path[8192]; ++#ifdef _WIN32 ++# define JOINER "\\" ++ SetLastError(ERROR_SUCCESS); ++ int result = GetModuleFileNameA(NULL, static_path, sizeof(static_path)); ++ if (GetLastError() != ERROR_SUCCESS) { ++ memcpy(static_path, DEFAULT_PATH, strlen(DEFAULT_PATH)); ++ } ++ char *pos = strrchr(static_path, '\\'); ++ if (pos) { ++ *pos = '\0'; ++ } ++#else ++# define JOINER "/" ++ ssize_t nb = readlink("/proc/self/exe", static_path, sizeof(static_path)); ++ if (nb != -1) { ++ static_path[nb] = '\0'; ++ dirname(static_path); ++ } else { ++ memcpy(static_path, DEFAULT_PATH, strlen(DEFAULT_PATH)); ++ } ++#endif ++ if (sizeof(static_path) < (strlen(static_path) + sizeof(JOINER) + strlen(filename) + 1)) { ++ strcpy(static_path, DEFAULT_PATH); ++ } ++ strncat(static_path, JOINER, sizeof(JOINER)); ++ strncat(static_path, filename, sizeof(filename)); ++ return static_path; ++} ++ + /* The next function finds the template file and opens it, returning + ** a pointer to the opened file. */ + PRIVATE FILE *tplt_open(struct lemon *lemp) + { +- static char templatename[] = "lempar.c"; ++ char *templatename; + char buf[1000]; + FILE *in; + char *tpltname; +@@ -3530,6 +3572,7 @@ + return in; + } + ++ templatename = get_default_template_path("lempar.c"); + cp = strrchr(lemp->filename,'.'); + if( cp ){ + lemon_sprintf(buf,"%.*s.lt",(int)(cp-lemp->filename),lemp->filename); diff --git a/recipes/lemon/all/test_package/CMakeLists.txt b/recipes/lemon/all/test_package/CMakeLists.txt new file mode 100644 index 0000000000000..288a9bc7d5d2c --- /dev/null +++ b/recipes/lemon/all/test_package/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 2.8.11) +project(test_package) + +include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) +conan_basic_setup() + +add_custom_command(OUTPUT gram.c gram.h + COMMAND lemon -s "${PROJECT_SOURCE_DIR}/gram.y" -d"${PROJECT_BINARY_DIR}" + BYPRODUCTS gram.out +) + +add_executable(${PROJECT_NAME} gram.c) +target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS}) diff --git a/recipes/lemon/all/test_package/conanfile.py b/recipes/lemon/all/test_package/conanfile.py new file mode 100644 index 0000000000000..287e10a174c2f --- /dev/null +++ b/recipes/lemon/all/test_package/conanfile.py @@ -0,0 +1,18 @@ +from conans import ConanFile, CMake, tools +import os + + +class TestPackageConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + generators = "cmake" + + def build(self): + if not tools.cross_building(self.settings): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + if not tools.cross_building(self.settings): + bin_path = os.path.join("bin", "test_package") + self.run(bin_path, run_environment=True) diff --git a/recipes/lemon/all/test_package/gram.y b/recipes/lemon/all/test_package/gram.y new file mode 100644 index 0000000000000..ffdacdab9288b --- /dev/null +++ b/recipes/lemon/all/test_package/gram.y @@ -0,0 +1,71 @@ +%include { +#include +#include +} + +%extra_argument {double *res} +%token_type {double} + +res ::= expr(B). { *res = B; } +expr(A) ::= expr(B) PLUS expr(C). { A = B + C; } +expr(A) ::= expr(B) MINUS expr(C). { A = B - C; } +expr(A) ::= expr(B) TIMES expr(C). { A = B * C; } +expr(A) ::= expr(B) DIVIDE expr(C). { A = B / C;} +expr(A) ::= expr(B) MOD expr(C). { A = modf(B, &C); } +expr(A) ::= LPAREN expr(B) RPAREN. { A = B; } +expr(A) ::= VALUE(B). { A = B; } +expr(A) ::= MINUS expr(B). [UMINUS] { A = -B; } + +%left PLUS MINUS. +%left TIMES DIVIDE MOD. +%right UMINUS. + +%code { + +#include "gram.h" + +typedef struct { + int id; + double val; +} input_item_t; + +static input_item_t test_input[] = { + {VALUE, 1.}, + {PLUS, 0.}, + {VALUE, 2.}, + {PLUS, 0.}, + {VALUE, 3.}, + {TIMES, 0.}, + {VALUE, 4.}, + {TIMES, 0.}, + {VALUE, 5.}, + {TIMES, 0.}, + {LPAREN, 0.}, + {VALUE, 6.}, + {MINUS, 0.}, + {VALUE, 7.}, + {RPAREN, 0.}, + {0., 0.}, +}; + +#include +#include + +int main(int argc, const char *argv[]) { + void *pParser = ParseAlloc(malloc); + double result = -123456.; + double val; + input_item_t *input = test_input; + while (1) { + Parse(pParser, input->id, input->val, &result); + if (input->id == 0) { + break; + } + ++input; + } + ParseFree(pParser, free); + printf("Result is %g.\n", result); + return 0; +} + +} diff --git a/recipes/lemon/config.yml b/recipes/lemon/config.yml new file mode 100644 index 0000000000000..2d5e8d76accb1 --- /dev/null +++ b/recipes/lemon/config.yml @@ -0,0 +1,3 @@ +"versions": + "3.32.3": + "folder": "all"