Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add lemon/3.32.3 recipe #2201

Merged
merged 10 commits into from
Aug 12, 2020
9 changes: 9 additions & 0 deletions recipes/lemon/all/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
8 changes: 8 additions & 0 deletions recipes/lemon/all/conandata.yml
Original file line number Diff line number Diff line change
@@ -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"
58 changes: 58 additions & 0 deletions recipes/lemon/all/conanfile.py
Original file line number Diff line number Diff line change
@@ -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"
uilianries marked this conversation as resolved.
Show resolved Hide resolved
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)
65 changes: 65 additions & 0 deletions recipes/lemon/all/patches/0001-use-executable-template-path.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
--- tool/lemon.c
+++ tool/lemon.c
@@ -3502,11 +3502,53 @@
}
}

+#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#else
+# include <libgen.h>
+# include <unistd.h>
+#endif
+#include <string.h>
+
+#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);
13 changes: 13 additions & 0 deletions recipes/lemon/all/test_package/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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})
17 changes: 17 additions & 0 deletions recipes/lemon/all/test_package/conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from conans import ConanFile, CMake, tools
import os


class TestPackageConan(ConanFile):
settings = "os", "compiler", "build_type", "arch"
generators = "cmake"

def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
madebr marked this conversation as resolved.
Show resolved Hide resolved

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)
71 changes: 71 additions & 0 deletions recipes/lemon/all/test_package/gram.y
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
%include {
#include <math.h>
#include <stdio.h>
}

%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 <stdio.h>
#include <stdlib.h>

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;
}

}
3 changes: 3 additions & 0 deletions recipes/lemon/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"versions":
"3.32.3":
"folder": "all"