From: Olivier Matz Date: Thu, 27 Oct 2016 15:59:44 +0000 (+0200) Subject: init X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=ca89e4f7548cb64e3dd1b67ea9ebb75ace33a754;p=protos%2Flibecoli.git init --- ca89e4f7548cb64e3dd1b67ea9ebb75ace33a754 diff --git a/lib/Makefile b/lib/Makefile new file mode 100644 index 0000000..0ce853f --- /dev/null +++ b/lib/Makefile @@ -0,0 +1,49 @@ +# +# Copyright 2016, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +ECOLI ?= $(abspath ..) +include $(ECOLI)/mk/ecoli-pre.mk + +# output path with trailing slash +O ?= build/ + +CFLAGS = -g -O0 -Wall -Werror -W -fPIC +CFLAGS += -I. + +srcs := ecoli_tk.c ecoli_tk_str.c ecoli_tk_seq.c +srcs += ecoli_tk_space.c ecoli_tk_or.c ecoli_test.c +srcs += ecoli_tk_empty.c ecoli_tk_int.c +shlib-y-$(O)libecoli.so := $(srcs) + +exe-y-$(O)test = $(srcs) main.c + +include $(ECOLI)/mk/ecoli-post.mk + +all: _ecoli_all + +clean: _ecoli_clean + +.PHONY: clean all diff --git a/lib/build/test b/lib/build/test new file mode 100755 index 0000000..ef61829 Binary files /dev/null and b/lib/build/test differ diff --git a/lib/ecoli_test.c b/lib/ecoli_test.c new file mode 100644 index 0000000..6b4a43f --- /dev/null +++ b/lib/ecoli_test.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include + +static struct ec_test_list test_list = TAILQ_HEAD_INITIALIZER(test_list); + +/* register a driver */ +void ec_test_register(struct ec_test *test) +{ + TAILQ_INSERT_TAIL(&test_list, test, next); +} + +int ec_test_check_tk_parse(const struct ec_tk *tk, const char *input, + const char *expected) +{ + struct ec_parsed_tk *p; + const char *s; + int ret = -1; + + p = ec_tk_parse(tk, input, 0); + s = ec_parsed_tk_to_string(p); + if (s == NULL && expected == NULL) + ret = 0; + else if (s != NULL && expected != NULL && + !strcmp(s, expected)) + ret = 0; + + if (expected == NULL && ret != 0) + printf("tk should not match but matches <%s>\n", s); + if (expected != NULL && ret != 0) + printf("tk should match <%s> but matches <%s>\n", + expected, s); + + ec_parsed_tk_free(p); + + return ret; +} + +int ec_test_check_tk_complete(const struct ec_tk *tk, const char *input, + const char *expected) +{ + struct ec_completed_tk *p; + const char *s; + int ret = -1; + + p = ec_tk_complete(tk, input, 0); + s = ec_completed_tk_smallest_start(p); + if (s == NULL && expected == NULL) + ret = 0; + else if (s != NULL && expected != NULL && + !strcmp(s, expected)) + ret = 0; + + if (expected == NULL && ret != 0) + printf("tk should not complete but completes with <%s>\n", s); + if (expected != NULL && ret != 0) + printf("tk should complete with <%s> but completes with <%s>\n", + expected, s); + + ec_completed_tk_free(p); + + return ret; +} + +/* int ec_test_check_tk_complete_list(const struct ec_tk *tk, */ +/* const char *input, ...) */ + +int ec_test_all(void) +{ + struct ec_test *test; + int ret = 0; + + // XXX register a new malloc to trac memleaks + + TAILQ_FOREACH(test, &test_list, next) { + if (test->test() == 0) { + printf("== test %-20s success\n", test->name); + } else { + printf("== test %-20s failed\n", test->name); + ret = -1; + } + } + + return ret; +} diff --git a/lib/ecoli_test.h b/lib/ecoli_test.h new file mode 100644 index 0000000..61d9950 --- /dev/null +++ b/lib/ecoli_test.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ECOLI_TEST_ +#define ECOLI_TEST_ + +#include + +#include + +#define EC_REGISTER_TEST(t) \ + static void ec_init_##t(void); \ + static void __attribute__((constructor, used)) ec_init_##t(void) \ + { \ + ec_test_register(&t); \ + } + +/** + * Type of test function. Return 0 on success, -1 on error. + */ +typedef int (ec_test_t)(void); + +TAILQ_HEAD(ec_test_list, ec_test); + +/** + * A structure describing a test case. + */ +struct ec_test { + TAILQ_ENTRY(ec_test) next; /**< Next in list. */ + const char *name; /**< Test name. */ + ec_test_t *test; /**< Test function. */ +}; + +/** + * Register a test case. + * + * @param test + * A pointer to a ec_test structure describing the test + * to be registered. + */ +void ec_test_register(struct ec_test *test); + +int ec_test_all(void); + +// XXX could be a macro that display file:line +int ec_test_check_tk_parse(const struct ec_tk *tk, const char *input, + const char *expected); + +#define TEST_ERR() \ + printf("%s:%d: error: test failed\n", \ + __FILE__, __LINE__); \ + +#define EC_TEST_CHECK_TK_PARSE(tk, input, expected) ({ \ + int ret = ec_test_check_tk_parse(tk, input, expected); \ + if (ret) \ + TEST_ERR(); \ + ret; \ +}) + +int ec_test_check_tk_complete(const struct ec_tk *tk, const char *input, + const char *expected); + +#define EC_TEST_CHECK_TK_COMPLETE(tk, input, expected) ({ \ + int ret = ec_test_check_tk_complete(tk, input, expected); \ + if (ret) \ + TEST_ERR(); \ + ret; \ +}) + +#endif diff --git a/lib/ecoli_tk.c b/lib/ecoli_tk.c new file mode 100644 index 0000000..7c5ac21 --- /dev/null +++ b/lib/ecoli_tk.c @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include + +struct ec_tk *ec_tk_new(const char *id, const struct ec_tk_ops *ops, + size_t size) +{ + struct ec_tk *tk = NULL; + + assert(size >= sizeof(*tk)); + + tk = calloc(1, size); + if (tk == NULL) + goto fail; + + if (id != NULL) { + tk->id = strdup(id); + if (tk->id == NULL) + goto fail; + } + + tk->ops = ops; + + return tk; + + fail: + ec_tk_free(tk); + return NULL; +} + +void ec_tk_free(struct ec_tk *tk) +{ + if (tk == NULL) + return; + + if (tk->ops != NULL && tk->ops->free_priv != NULL) + tk->ops->free_priv(tk); + free(tk->id); + free(tk); +} + +struct ec_parsed_tk *ec_tk_parse(const struct ec_tk *token, const char *str, + size_t off) +{ + struct ec_parsed_tk *parsed_tk; + + parsed_tk = token->ops->parse(token, str, off); + + return parsed_tk; +} + + +struct ec_parsed_tk *ec_parsed_tk_new(const struct ec_tk *tk) +{ + struct ec_parsed_tk *parsed_tk; + + parsed_tk = calloc(1, sizeof(*parsed_tk)); + if (parsed_tk == NULL) + goto fail; + + parsed_tk->tk = tk; + TAILQ_INIT(&parsed_tk->children); + + return parsed_tk; + + fail: + return NULL; +} + +void ec_parsed_tk_free(struct ec_parsed_tk *parsed_tk) +{ + struct ec_parsed_tk *child; + + if (parsed_tk == NULL) + return; + + while (!TAILQ_EMPTY(&parsed_tk->children)) { + child = TAILQ_FIRST(&parsed_tk->children); + TAILQ_REMOVE(&parsed_tk->children, child, next); + ec_parsed_tk_free(child); + } + free(parsed_tk->str); + free(parsed_tk); +} + +static void __ec_parsed_tk_dump(const struct ec_parsed_tk *parsed_tk, + size_t indent) +{ + struct ec_parsed_tk *child; + size_t i; + const char *s; + + /* XXX enhance */ + for (i = 0; i < indent; i++) + printf(" "); + s = ec_parsed_tk_to_string(parsed_tk); + printf("id=%s, s=<%s>\n", parsed_tk->tk->id, s); + + TAILQ_FOREACH(child, &parsed_tk->children, next) + __ec_parsed_tk_dump(child, indent + 2); +} + +void ec_parsed_tk_dump(const struct ec_parsed_tk *parsed_tk) +{ + if (parsed_tk == NULL) { + printf("no match\n"); + return; + } + + __ec_parsed_tk_dump(parsed_tk, 0); +} + +void ec_parsed_tk_add_child(struct ec_parsed_tk *parsed_tk, + struct ec_parsed_tk *child) +{ + TAILQ_INSERT_TAIL(&parsed_tk->children, child, next); +} + +struct ec_parsed_tk *ec_parsed_tk_find_first(struct ec_parsed_tk *parsed_tk, + const char *id) +{ + struct ec_parsed_tk *child, *ret; + + if (parsed_tk == NULL) + return NULL; + + if (parsed_tk->tk->id != NULL && !strcmp(parsed_tk->tk->id, id)) + return parsed_tk; + + TAILQ_FOREACH(child, &parsed_tk->children, next) { + ret = ec_parsed_tk_find_first(child, id); + if (ret != NULL) + return ret; + } + + return NULL; +} + +const char *ec_parsed_tk_to_string(const struct ec_parsed_tk *parsed_tk) +{ + if (parsed_tk == NULL) + return NULL; + + return parsed_tk->str; +} + +struct ec_completed_tk *ec_tk_complete(const struct ec_tk *token, + const char *str, size_t off) +{ + struct ec_completed_tk *completed_tk; + + completed_tk = token->ops->complete(token, str, off); + + return completed_tk; +} + +struct ec_completed_tk *ec_completed_tk_new(void) +{ + struct ec_completed_tk *completed_tk = NULL; + + completed_tk = calloc(1, sizeof(*completed_tk)); + if (completed_tk == NULL) + return NULL; + + TAILQ_INIT(&completed_tk->elts); + completed_tk->count = 0; + + return completed_tk; +} + +struct ec_completed_tk_elt *ec_completed_tk_elt_new(const struct ec_tk *tk, + const char *add, const char *full) +{ + struct ec_completed_tk_elt *elt = NULL; + + elt = calloc(1, sizeof(*elt)); + if (elt == NULL) + return NULL; + + elt->tk = tk; + elt->add = strdup(add); + elt->full = strdup(full); + if (elt->add == NULL || elt->full == NULL) { + ec_completed_tk_elt_free(elt); + return NULL; + } + + return elt; +} + +/* count the number of identical chars at the beginning of 2 strings */ +static size_t strcmp_count(const char *s1, const char *s2) +{ + size_t i = 0; + + while (s1[i] && s2[i] && s1[i] == s2[i]) + i++; + + return i; +} + +void ec_completed_tk_add_elt( + struct ec_completed_tk *completed_tk, struct ec_completed_tk_elt *elt) +{ + size_t n; + + TAILQ_INSERT_TAIL(&completed_tk->elts, elt, next); + completed_tk->count++; + if (elt->add != NULL) { + if (completed_tk->smallest_start == NULL) { + completed_tk->smallest_start = strdup(elt->add); + } else { + n = strcmp_count(elt->add, + completed_tk->smallest_start); + completed_tk->smallest_start[n] = '\0'; + } + } +} + +void ec_completed_tk_elt_free(struct ec_completed_tk_elt *elt) +{ + free(elt->add); + free(elt->full); + free(elt); +} + +struct ec_completed_tk *ec_completed_tk_merge( + struct ec_completed_tk *completed_tk1, + struct ec_completed_tk *completed_tk2) +{ + struct ec_completed_tk_elt *elt; + + if (completed_tk2 == NULL) + return completed_tk1; + + if (completed_tk1 == NULL) + return completed_tk2; + + while (!TAILQ_EMPTY(&completed_tk2->elts)) { + elt = TAILQ_FIRST(&completed_tk2->elts); + TAILQ_REMOVE(&completed_tk2->elts, elt, next); + ec_completed_tk_add_elt(completed_tk1, elt); + } + + ec_completed_tk_free(completed_tk2); + + return completed_tk1; +} + +void ec_completed_tk_free(struct ec_completed_tk *completed_tk) +{ + struct ec_completed_tk_elt *elt; + + if (completed_tk == NULL) + return; + + while (!TAILQ_EMPTY(&completed_tk->elts)) { + elt = TAILQ_FIRST(&completed_tk->elts); + TAILQ_REMOVE(&completed_tk->elts, elt, next); + ec_completed_tk_elt_free(elt); + } + free(completed_tk->smallest_start); + free(completed_tk); +} + +void ec_completed_tk_dump(const struct ec_completed_tk *completed_tk) +{ + struct ec_completed_tk_elt *elt; + + if (completed_tk == NULL || completed_tk->count == 0) { + printf("no completion\n"); + return; + } + + printf("completion: count=%u smallest_start=<%s>\n", + completed_tk->count, completed_tk->smallest_start); + + TAILQ_FOREACH(elt, &completed_tk->elts, next) + printf("add=<%s> full=<%s>\n", elt->add, elt->full); +} + +const char *ec_completed_tk_smallest_start( + const struct ec_completed_tk *completed_tk) +{ + if (completed_tk == NULL) + return NULL; + + return completed_tk->smallest_start; +} + +unsigned int ec_completed_tk_count(const struct ec_completed_tk *completed_tk) +{ + struct ec_completed_tk_elt *elt; + unsigned int count = 0; + + if (completed_tk == NULL) + return 0; + + TAILQ_FOREACH(elt, &completed_tk->elts, next) + count++; + + return count; +} diff --git a/lib/ecoli_tk.h b/lib/ecoli_tk.h new file mode 100644 index 0000000..15be2be --- /dev/null +++ b/lib/ecoli_tk.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ECOLI_TK_ +#define ECOLI_TK_ + +#include +#include + +#define EC_TK_ENDLIST ((void *)1) + +struct ec_tk; +struct ec_parsed_tk; + +typedef struct ec_parsed_tk *(*ec_tk_parse_t)(const struct ec_tk *tk, + const char *str, size_t off); +typedef struct ec_completed_tk *(*ec_tk_complete_t)(const struct ec_tk *tk, + const char *str, size_t off); +typedef void (*ec_tk_free_priv_t)(struct ec_tk *); + +struct ec_tk_ops { + ec_tk_parse_t parse; + ec_tk_complete_t complete; + ec_tk_free_priv_t free_priv; +}; + +struct ec_tk { + const struct ec_tk_ops *ops; + char *id; +}; + +struct ec_tk *ec_tk_new(const char *id, const struct ec_tk_ops *ops, + size_t priv_size); +void ec_tk_free(struct ec_tk *tk); + + +TAILQ_HEAD(ec_parsed_tk_list, ec_parsed_tk); + +struct ec_parsed_tk { + struct ec_parsed_tk_list children; + TAILQ_ENTRY(ec_parsed_tk) next; + const struct ec_tk *tk; + char *str; +}; + +struct ec_parsed_tk *ec_parsed_tk_new(const struct ec_tk *tk); +struct ec_parsed_tk *ec_tk_parse(const struct ec_tk *token, const char *str, + size_t off); +void ec_parsed_tk_add_child(struct ec_parsed_tk *parsed_tk, + struct ec_parsed_tk *child); +void ec_parsed_tk_dump(const struct ec_parsed_tk *parsed_tk); +void ec_parsed_tk_free(struct ec_parsed_tk *parsed_tk); + +struct ec_parsed_tk *ec_parsed_tk_find_first(struct ec_parsed_tk *parsed_tk, + const char *id); + +const char *ec_parsed_tk_to_string(const struct ec_parsed_tk *parsed_tk); + +struct ec_completed_tk_elt { + TAILQ_ENTRY(ec_completed_tk_elt) next; + const struct ec_tk *tk; + char *add; + char *full; +}; + +TAILQ_HEAD(ec_completed_tk_elt_list, ec_completed_tk_elt); + + +struct ec_completed_tk { + struct ec_completed_tk_elt_list elts; + unsigned count; + char *smallest_start; +}; + +/* + * return NULL if it does not match the beginning of the token + * return "" if it matches but does not know how to complete + * return "xyz" if it knows how to complete + */ +struct ec_completed_tk *ec_tk_complete(const struct ec_tk *token, + const char *str, size_t off); +struct ec_completed_tk *ec_completed_tk_new(void); +struct ec_completed_tk_elt *ec_completed_tk_elt_new(const struct ec_tk *tk, + const char *add, const char *full); +void ec_completed_tk_add_elt( + struct ec_completed_tk *completed_tk, struct ec_completed_tk_elt *elt); +void ec_completed_tk_elt_free(struct ec_completed_tk_elt *elt); +struct ec_completed_tk *ec_completed_tk_merge( + struct ec_completed_tk *completed_tk1, + struct ec_completed_tk *completed_tk2); +void ec_completed_tk_free(struct ec_completed_tk *completed_tk); +void ec_completed_tk_dump(const struct ec_completed_tk *completed_tk); + +const char *ec_completed_tk_smallest_start( + const struct ec_completed_tk *completed_tk); + +unsigned int ec_completed_tk_count(const struct ec_completed_tk *completed_tk); + +#endif diff --git a/lib/ecoli_tk_empty.c b/lib/ecoli_tk_empty.c new file mode 100644 index 0000000..e8e98e1 --- /dev/null +++ b/lib/ecoli_tk_empty.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include + +static struct ec_parsed_tk *parse(const struct ec_tk *gen_tk, + const char *str, size_t off) +{ + struct ec_parsed_tk *parsed_tk; + + parsed_tk = ec_parsed_tk_new(gen_tk); + if (parsed_tk == NULL) + return NULL; + + (void)str; + (void)off; + parsed_tk->str = strdup(""); + + return parsed_tk; +} + +static struct ec_tk_ops empty_ops = { + .parse = parse, +}; + +struct ec_tk *ec_tk_empty_new(const char *id) +{ + return ec_tk_new(id, &empty_ops, sizeof(struct ec_tk_empty)); +} + diff --git a/lib/ecoli_tk_empty.h b/lib/ecoli_tk_empty.h new file mode 100644 index 0000000..4e22420 --- /dev/null +++ b/lib/ecoli_tk_empty.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ECOLI_TK_EMPTY_ +#define ECOLI_TK_EMPTY_ + +#include + +struct ec_tk_empty { + struct ec_tk gen; +}; + +struct ec_tk *ec_tk_empty_new(const char *id); + +#endif diff --git a/lib/ecoli_tk_int.c b/lib/ecoli_tk_int.c new file mode 100644 index 0000000..6bd4bfd --- /dev/null +++ b/lib/ecoli_tk_int.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static size_t parse_llint(struct ec_tk_int *tk, const char *str, + long long *val) +{ + char *endptr; + + errno = 0; + *val = strtoll(str, &endptr, tk->base); + + /* starts with a space */ + if (isspace(str[0])) + return 0; + + /* out of range */ + if ((errno == ERANGE && (*val == LLONG_MAX || *val == LLONG_MIN)) || + (errno != 0 && *val == 0)) + return 0; + + if (*val < tk->min || *val > tk->max) + return 0; + + return endptr - str; +} + +static struct ec_parsed_tk *parse(const struct ec_tk *gen_tk, + const char *str, size_t off) +{ + struct ec_tk_int *tk = (struct ec_tk_int *)gen_tk; + struct ec_parsed_tk *parsed_tk; + long long val; + size_t len; + + len = parse_llint(tk, str + off, &val); + if (len == 0) + return NULL; + + parsed_tk = ec_parsed_tk_new(gen_tk); + if (parsed_tk == NULL) + return NULL; + + parsed_tk->str = strndup(str + off, len); + + return parsed_tk; +} + +static struct ec_tk_ops int_ops = { + .parse = parse, +}; + +struct ec_tk *ec_tk_int_new(const char *id, long long int min, + long long int max, unsigned int base) +{ + struct ec_tk_int *tk = NULL; + + tk = (struct ec_tk_int *)ec_tk_new(id, &int_ops, sizeof(*tk)); + if (tk == NULL) + return NULL; + + tk->min = min; + tk->max = max; + tk->base = base; + + return &tk->gen; +} + +long long ec_tk_int_getval(struct ec_tk *gen_tk, const char *str) +{ + struct ec_tk_int *tk = (struct ec_tk_int *)gen_tk; + long long val = 0; + + // XXX check type here + // if gen_tk->type != int fail + + parse_llint(tk, str, &val); + + return val; +} + +static int testcase(void) +{ + struct ec_parsed_tk *p; + struct ec_tk *tk; + const char *s; + int ret = 0; + + tk = ec_tk_int_new(NULL, 0, 256, 0); + if (tk == NULL) { + printf("cannot create tk\n"); + return -1; + } + ret |= EC_TEST_CHECK_TK_PARSE(tk, "0", "0"); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "256", "256"); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "0x100", "0x100"); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "-1", NULL); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "0x101", NULL); + ret |= EC_TEST_CHECK_TK_PARSE(tk, " 1", NULL); + + p = ec_tk_parse(tk, "0", 0); + s = ec_parsed_tk_to_string(p); + if (s == NULL) { + TEST_ERR(); + } else { + if (ec_tk_int_getval(tk, s) != 0) + TEST_ERR(); + } + + p = ec_tk_parse(tk, "10", 0); + s = ec_parsed_tk_to_string(p); + if (s == NULL) { + TEST_ERR(); + } else { + if (ec_tk_int_getval(tk, s) != 10) + TEST_ERR(); + } + + ec_tk_free(tk); + + tk = ec_tk_int_new(NULL, -1, LLONG_MAX, 16); + if (tk == NULL) { + printf("cannot create tk\n"); + return -1; + } + ret |= EC_TEST_CHECK_TK_PARSE(tk, "0", "0"); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "-1", "-1"); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "7fffffffffffffff", + "7fffffffffffffff"); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "0x7fffffffffffffff", + "0x7fffffffffffffff"); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "-2", NULL); + + p = ec_tk_parse(tk, "10", 0); + s = ec_parsed_tk_to_string(p); + if (s == NULL) { + TEST_ERR(); + } else { + if (ec_tk_int_getval(tk, s) != 16) + TEST_ERR(); + } + + ec_tk_free(tk); + + tk = ec_tk_int_new(NULL, LLONG_MIN, 0, 10); + if (tk == NULL) { + printf("cannot create tk\n"); + return -1; + } + ret |= EC_TEST_CHECK_TK_PARSE(tk, "0", "0"); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "-1", "-1"); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "-9223372036854775808", + "-9223372036854775808"); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "0x0", "0"); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "1", NULL); + ec_tk_free(tk); + + /* /\* test completion *\/ */ + /* tk = ec_tk_int_new(NULL, "foo"); */ + /* if (tk == NULL) { */ + /* printf("cannot create tk\n"); */ + /* return -1; */ + /* } */ + /* ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "", "foo"); */ + /* ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "f", "oo"); */ + /* ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "foo", ""); */ + /* ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "x", NULL); */ + /* ec_tk_free(tk); */ + + return ret; +} + +static struct ec_test test = { + .name = "tk_int", + .test = testcase, +}; + +EC_REGISTER_TEST(test); diff --git a/lib/ecoli_tk_int.h b/lib/ecoli_tk_int.h new file mode 100644 index 0000000..e210279 --- /dev/null +++ b/lib/ecoli_tk_int.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ECOLI_TK_INT_ +#define ECOLI_TK_INT_ + +#include + +struct ec_tk_int { + struct ec_tk gen; + long long int min; + long long int max; + unsigned int base; +}; + +struct ec_tk *ec_tk_int_new(const char *id, long long int min, + long long int max, unsigned int base); +long long ec_tk_int_getval(struct ec_tk *tk, const char *str); + +#endif diff --git a/lib/ecoli_tk_or.c b/lib/ecoli_tk_or.c new file mode 100644 index 0000000..dda2230 --- /dev/null +++ b/lib/ecoli_tk_or.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static struct ec_parsed_tk *parse(const struct ec_tk *gen_tk, + const char *str, size_t off) +{ + struct ec_tk_or *tk = (struct ec_tk_or *)gen_tk; + struct ec_parsed_tk *parsed_tk, *child_parsed_tk; + unsigned int i; + + parsed_tk = ec_parsed_tk_new(gen_tk); + if (parsed_tk == NULL) + return NULL; + + for (i = 0; i < tk->len; i++) { + child_parsed_tk = ec_tk_parse(tk->table[i], str, off); + if (child_parsed_tk != NULL) + break; + } + + if (child_parsed_tk == NULL) + goto fail; + + ec_parsed_tk_add_child(parsed_tk, child_parsed_tk); + + parsed_tk->str = strndup(child_parsed_tk->str, + strlen(child_parsed_tk->str)); + + return parsed_tk; + + fail: + ec_parsed_tk_free(parsed_tk); + return NULL; +} + +static struct ec_completed_tk *complete(const struct ec_tk *gen_tk, + const char *str, size_t off) +{ + struct ec_tk_or *tk = (struct ec_tk_or *)gen_tk; + struct ec_completed_tk *completed_tk = NULL, *child_completed_tk; + size_t n; + + for (n = 0; n < tk->len; n++) { + child_completed_tk = ec_tk_complete(tk->table[n], str, off); + + if (child_completed_tk == NULL) + continue; + + completed_tk = ec_completed_tk_merge(completed_tk, + child_completed_tk); + } + + return completed_tk; +} + +static void free_priv(struct ec_tk *gen_tk) +{ + struct ec_tk_or *tk = (struct ec_tk_or *)gen_tk; + + free(tk->table); +} + +static struct ec_tk_ops or_ops = { + .parse = parse, + .complete = complete, + .free_priv = free_priv, +}; + +struct ec_tk *ec_tk_or_new(const char *id) +{ + struct ec_tk_or *tk = NULL; + + tk = (struct ec_tk_or *)ec_tk_new(id, &or_ops, sizeof(*tk)); + if (tk == NULL) + goto fail; + + tk->table = NULL; + tk->len = 0; + + return &tk->gen; + +fail: + free(tk); + return NULL; +} + +struct ec_tk *ec_tk_or_new_list(const char *id, ...) +{ + struct ec_tk_or *tk = NULL; + struct ec_tk *child; + va_list ap; + + va_start(ap, id); + + tk = (struct ec_tk_or *)ec_tk_or_new(id); + if (tk == NULL) + goto fail; + + for (child = va_arg(ap, struct ec_tk *); + child != EC_TK_ENDLIST; + child = va_arg(ap, struct ec_tk *)) { + if (child == NULL) + goto fail; + + ec_tk_or_add(&tk->gen, child); + } + + va_end(ap); + return &tk->gen; + +fail: + free(tk); // XXX use tk_free? we need to delete all child on error + va_end(ap); + return NULL; +} + +int ec_tk_or_add(struct ec_tk *tk, struct ec_tk *child) +{ + struct ec_tk_or *or = (struct ec_tk_or *)tk; + struct ec_tk **table; + + assert(tk != NULL); + assert(child != NULL); + + table = realloc(or->table, (or->len + 1) * sizeof(*or->table)); + if (table == NULL) + return -1; + + or->table = table; + table[or->len] = child; + or->len ++; + + return 0; +} + +static int testcase(void) +{ + struct ec_tk *tk; + int ret = 0; + + /* all inputs starting with foo should match */ + tk = ec_tk_or_new_list(NULL, + ec_tk_str_new(NULL, "foo"), + ec_tk_str_new(NULL, "bar"), + EC_TK_ENDLIST); + if (tk == NULL) { + printf("cannot create tk\n"); + return -1; + } + ret |= EC_TEST_CHECK_TK_PARSE(tk, "foo", "foo"); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "fooxxx", "foo"); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "bar", "bar"); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "oo", NULL); + ec_tk_free(tk); + + /* test completion */ + tk = ec_tk_or_new_list(NULL, + ec_tk_str_new(NULL, "foo"), + ec_tk_str_new(NULL, "bar"), + ec_tk_str_new(NULL, "bar2"), + ec_tk_str_new(NULL, "toto"), + ec_tk_str_new(NULL, "titi"), + EC_TK_ENDLIST); + if (tk == NULL) { + printf("cannot create tk\n"); + return -1; + } + ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "", ""); + ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "f", "oo"); + ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "b", "ar"); + ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "t", ""); + ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "to", "to"); + ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "x", NULL); + ec_tk_free(tk); + + return ret; +} + +static struct ec_test test = { + .name = "tk_or", + .test = testcase, +}; + +EC_REGISTER_TEST(test); diff --git a/lib/ecoli_tk_or.h b/lib/ecoli_tk_or.h new file mode 100644 index 0000000..130ec4d --- /dev/null +++ b/lib/ecoli_tk_or.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ECOLI_TK_OR_ +#define ECOLI_TK_OR_ + +#include + +#include + +struct ec_tk_or { + struct ec_tk gen; + struct ec_tk **table; + unsigned int len; +}; + +struct ec_tk *ec_tk_or_new(const char *id); + +/* list must be terminated with EC_TK_ENDLIST */ +struct ec_tk *ec_tk_or_new_list(const char *id, ...); + +int ec_tk_or_add(struct ec_tk *tk, struct ec_tk *child); + +#endif diff --git a/lib/ecoli_tk_seq.c b/lib/ecoli_tk_seq.c new file mode 100644 index 0000000..38c633a --- /dev/null +++ b/lib/ecoli_tk_seq.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include +#include + +static struct ec_parsed_tk *parse(const struct ec_tk *tk, + const char *str, size_t off) +{ + struct ec_tk_seq *seq = (struct ec_tk_seq *)tk; + struct ec_parsed_tk *parsed_tk, *child_parsed_tk; + size_t len = 0; + unsigned int i; + + parsed_tk = ec_parsed_tk_new(tk); + if (parsed_tk == NULL) + return NULL; + + for (i = 0; i < seq->len; i++) { + child_parsed_tk = ec_tk_parse(seq->table[i], str, off + len); + if (child_parsed_tk == NULL) + goto fail; + + len += strlen(child_parsed_tk->str); + ec_parsed_tk_add_child(parsed_tk, child_parsed_tk); + } + + parsed_tk->str = strndup(str + off, len); + + return parsed_tk; + + fail: + ec_parsed_tk_free(parsed_tk); + return NULL; +} + +static struct ec_tk_ops seq_ops = { + .parse = parse, +}; + +struct ec_tk *ec_tk_seq_new(const char *id) +{ + struct ec_tk_seq *tk = NULL; + + tk = (struct ec_tk_seq *)ec_tk_new(id, &seq_ops, sizeof(*tk)); + if (tk == NULL) + goto fail; + + tk->table = NULL; + tk->len = 0; + + return &tk->gen; + +fail: + free(tk); + return NULL; +} + +struct ec_tk *ec_tk_seq_new_list(const char *id, ...) +{ + struct ec_tk_seq *tk = NULL; + struct ec_tk *child; + va_list ap; + + va_start(ap, id); + + tk = (struct ec_tk_seq *)ec_tk_seq_new(id); + if (tk == NULL) + goto fail; + + for (child = va_arg(ap, struct ec_tk *); + child != EC_TK_ENDLIST; + child = va_arg(ap, struct ec_tk *)) { + if (child == NULL) + goto fail; + + ec_tk_seq_add(&tk->gen, child); + } + + va_end(ap); + return &tk->gen; + +fail: + free(tk); // XXX use tk_free? we need to delete all child on error + va_end(ap); + return NULL; +} + +int ec_tk_seq_add(struct ec_tk *tk, struct ec_tk *child) +{ + struct ec_tk_seq *seq = (struct ec_tk_seq *)tk; + struct ec_tk **table; + + assert(tk != NULL); + assert(child != NULL); + + table = realloc(seq->table, seq->len + 1); + if (table == NULL) + return -1; + + seq->table = table; + table[seq->len] = child; + seq->len ++; + + return 0; +} + diff --git a/lib/ecoli_tk_seq.h b/lib/ecoli_tk_seq.h new file mode 100644 index 0000000..5c7bfed --- /dev/null +++ b/lib/ecoli_tk_seq.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ECOLI_TK_SEQ_ +#define ECOLI_TK_SEQ_ + +#include + +#include + +struct ec_tk_seq { + struct ec_tk gen; + struct ec_tk **table; + unsigned int len; +}; + +struct ec_tk *ec_tk_seq_new(const char *id); + +/* list must be terminated with EC_TK_ENDLIST */ +struct ec_tk *ec_tk_seq_new_list(const char *id, ...); + +int ec_tk_seq_add(struct ec_tk *tk, struct ec_tk *child); + +#endif diff --git a/lib/ecoli_tk_space.c b/lib/ecoli_tk_space.c new file mode 100644 index 0000000..ed2ee31 --- /dev/null +++ b/lib/ecoli_tk_space.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include +#include + +static struct ec_parsed_tk *parse(const struct ec_tk *gen_tk, + const char *str, size_t off) +{ + struct ec_parsed_tk *parsed_tk; + size_t len = 0; + + if (!isspace(str[off])) + return NULL; + + parsed_tk = ec_parsed_tk_new(gen_tk); + if (parsed_tk == NULL) + return NULL; + + while (isspace(str[off + len])) + len++; + + parsed_tk->str = strndup(str + off, len); + + return parsed_tk; +} + +static struct ec_tk_ops space_ops = { + .parse = parse, +}; + +struct ec_tk *ec_tk_space_new(const char *id) +{ + return ec_tk_new(id, &space_ops, sizeof(struct ec_tk_space)); +} + diff --git a/lib/ecoli_tk_space.h b/lib/ecoli_tk_space.h new file mode 100644 index 0000000..6327c8a --- /dev/null +++ b/lib/ecoli_tk_space.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ECOLI_TK_SPACE_ +#define ECOLI_TK_SPACE_ + +#include + +struct ec_tk_space { + struct ec_tk gen; +}; + +struct ec_tk *ec_tk_space_new(const char *id); + +#endif diff --git a/lib/ecoli_tk_str.c b/lib/ecoli_tk_str.c new file mode 100644 index 0000000..8152704 --- /dev/null +++ b/lib/ecoli_tk_str.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include +#include + +static struct ec_parsed_tk *parse(const struct ec_tk *gen_tk, + const char *str, size_t off) +{ + struct ec_tk_str *tk = (struct ec_tk_str *)gen_tk; + struct ec_parsed_tk *parsed_tk; + + if (strncmp(str + off, tk->string, tk->len) != 0) + return NULL; + + parsed_tk = ec_parsed_tk_new(gen_tk); + if (parsed_tk == NULL) + return NULL; + + parsed_tk->str = strndup(str + off, tk->len); + + return parsed_tk; +} + +static struct ec_completed_tk *complete(const struct ec_tk *gen_tk, + const char *str, size_t off) +{ + struct ec_tk_str *tk = (struct ec_tk_str *)gen_tk; + struct ec_completed_tk *completed_tk; + struct ec_completed_tk_elt *completed_tk_elt; + size_t n; + + for (n = 0; n < tk->len; n++) { + if (str[off + n] != tk->string[n]) + break; + } + + if (str[off + n] != '\0') + return NULL; + + completed_tk = ec_completed_tk_new(); + if (completed_tk == NULL) + return NULL; + + completed_tk_elt = ec_completed_tk_elt_new(gen_tk, tk->string + n, + tk->string); + if (completed_tk_elt == NULL) { + ec_completed_tk_free(completed_tk); + return NULL; + } + + ec_completed_tk_add_elt(completed_tk, completed_tk_elt); + + return completed_tk; +} + +static void free_priv(struct ec_tk *gen_tk) +{ + struct ec_tk_str *tk = (struct ec_tk_str *)gen_tk; + + free(tk->string); +} + +static struct ec_tk_ops str_ops = { + .parse = parse, + .complete = complete, + .free_priv = free_priv, +}; + +struct ec_tk *ec_tk_str_new(const char *id, const char *str) +{ + struct ec_tk_str *tk = NULL; + char *s = NULL; + + tk = (struct ec_tk_str *)ec_tk_new(id, &str_ops, sizeof(*tk)); + if (tk == NULL) + goto fail; + + s = strdup(str); + if (s == NULL) + goto fail; + + tk->string = s; + tk->len = strlen(s); + + return &tk->gen; + +fail: + free(s); + free(tk); + return NULL; +} + +static int testcase(void) +{ + struct ec_tk *tk; + int ret = 0; + + /* all inputs starting with foo should match */ + tk = ec_tk_str_new(NULL, "foo"); + if (tk == NULL) { + printf("cannot create tk\n"); + return -1; + } + ret |= EC_TEST_CHECK_TK_PARSE(tk, "foo", "foo"); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "foobar", "foo"); + ret |= EC_TEST_CHECK_TK_PARSE(tk, " foo", NULL); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "", NULL); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "foo", "foo"); + ec_tk_free(tk); + + /* all inputs starting with foo should match */ + tk = ec_tk_str_new(NULL, "Здравствуйте"); + if (tk == NULL) { + printf("cannot create tk\n"); + return -1; + } + ret |= EC_TEST_CHECK_TK_PARSE(tk, "Здравствуйте", "Здравствуйте"); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "Здравствуйте John!", "Здравствуйте"); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "foo", NULL); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "", NULL); + ec_tk_free(tk); + + /* an empty token string always matches */ + tk = ec_tk_str_new(NULL, ""); + if (tk == NULL) { + printf("cannot create tk\n"); + return -1; + } + ret |= EC_TEST_CHECK_TK_PARSE(tk, "", ""); + ret |= EC_TEST_CHECK_TK_PARSE(tk, "foo", ""); + ec_tk_free(tk); + + /* test completion */ + tk = ec_tk_str_new(NULL, "foo"); + if (tk == NULL) { + printf("cannot create tk\n"); + return -1; + } + ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "", "foo"); + ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "f", "oo"); + ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "foo", ""); + ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "x", NULL); + ec_tk_free(tk); + + return ret; +} + +static struct ec_test test = { + .name = "tk_str", + .test = testcase, +}; + +EC_REGISTER_TEST(test); diff --git a/lib/ecoli_tk_str.h b/lib/ecoli_tk_str.h new file mode 100644 index 0000000..e7c0759 --- /dev/null +++ b/lib/ecoli_tk_str.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ECOLI_TK_STR_ +#define ECOLI_TK_STR_ + +#include + +struct ec_tk_str { + struct ec_tk gen; + char *string; + unsigned len; +}; + +struct ec_tk *ec_tk_str_new(const char *id, const char *str); + +#endif diff --git a/lib/main.c b/lib/main.c new file mode 100644 index 0000000..54057b7 --- /dev/null +++ b/lib/main.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016, Olivier MATZ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the University of California, Berkeley nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +static void test(void) +{ + struct ec_tk *seq; + struct ec_parsed_tk *p; + const char *name; + + seq = ec_tk_seq_new_list(NULL, + ec_tk_str_new(NULL, "hello"), + ec_tk_space_new(NULL), + ec_tk_or_new_list("name", + ec_tk_str_new(NULL, "john"), + ec_tk_str_new(NULL, "mike"), + EC_TK_ENDLIST), + EC_TK_ENDLIST); + if (seq == NULL) { + printf("cannot create token\n"); + return; + } + + /* ok */ + p = ec_tk_parse(seq, "hello mike", 0); + ec_parsed_tk_dump(p); + name = ec_parsed_tk_to_string(ec_parsed_tk_find_first(p, "name")); + printf("parsed with name=%s\n", name); + ec_parsed_tk_free(p); + + /* ko */ + p = ec_tk_parse(seq, "hello robert", 0); + ec_parsed_tk_dump(p); + name = ec_parsed_tk_to_string(ec_parsed_tk_find_first(p, "name")); + printf("parsed with name=%s\n", name); + ec_parsed_tk_free(p); + + ec_tk_free(seq); +} + +int main(void) +{ + ec_test_all(); + + test(); + + return 0; +} diff --git a/mk/ecoli-ar-rules.mk b/mk/ecoli-ar-rules.mk new file mode 100644 index 0000000..4ad30cb --- /dev/null +++ b/mk/ecoli-ar-rules.mk @@ -0,0 +1,55 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# dump some infos if debug is enabled +ifeq ($(D),1) +$(call disp_list,------ all-ar,$(all-ar)) +$(foreach ar,$(all-ar),\ + $(info,out-$(ar): $(out-$(ar))) \ + $(call disp_list,pre-$(ar),$(pre-$(ar))) \ +) +endif + +# include dependencies and commands files if they exist +$(foreach ar,$(all-ar),\ + $(eval -include $(call depfile,$(ar))) \ + $(eval -include $(call cmdfile,$(ar))) \ +) + +# remove duplicates +filtered-all-ar := $(sort $(all-ar)) + +# link several objects files into one shared object +$(filtered-all-ar): $$(pre-$$@) $$(wildcard $$(dep-$$@)) FORCE + @[ -d $(dir $@) ] || mkdir -p $(dir $@) + @$(call display_deps,$(pre-$(@)),$@,\ + $(call ar_cmd,$(pre-$(@)),$@),$?) + @$(if $(call check_deps,$@,$(call ar_cmd,$(pre-$(@)),$@),$?),\ + $(call ar_print_cmd,$(pre-$(@)),$@) && \ + $(call ar_cmd,$(pre-$(@)),$@) && \ + $(call save_cmd,$(call ar_cmd,$(pre-$(@)),$@),$@) && \ + $(call create_empty_depfile,$@)) diff --git a/mk/ecoli-ar-vars.mk b/mk/ecoli-ar-vars.mk new file mode 100644 index 0000000..7d2fab7 --- /dev/null +++ b/mk/ecoli-ar-vars.mk @@ -0,0 +1,75 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# ar-y-$(ar) is provided by the user +# $(ar) is the path of the static library, and the variable contains +# the list of sources. Several ar-y-$(ar) can be present. + +# list all ar builds requested by user +all-ar := $(patsubst ar-y-%,%,$(filter ar-y-%,$(.VARIABLES))) + +# add them to the list of targets +all-targets += $(all-ar) + +# for each ar, create the following variables: +# out-$(ar) = output path of the arcutable +# pre-$(ar) = list of prerequisites for this arcutable +# Some source files need intermediate objects, we define these variables +# for them too, and add them in a list: $(all-iobj). +# Last, we add the generated files in $(all-clean-file). +$(foreach ar,$(all-ar),\ + $(eval out-$(ar) := $(dir $(ar))) \ + $(eval pre-$(ar) := ) \ + $(foreach src,$(ar-y-$(ar)), \ + $(if $(call is_cc_source,$(src)), \ + $(eval iobj := $(call src2iobj,$(src),$(out-$(ar)))) \ + $(eval pre-$(iobj) := $(src)) \ + $(eval all-iobj += $(iobj)) \ + $(eval all-clean-file += $(iobj)) \ + $(eval pre-$(ar) += $(iobj)) \ + , \ + $(if $(call is_obj_source,$(src)),\ + $(eval pre-$(ar) += $(src)) \ + , \ + $(error "unsupported source format: $(src)"))) \ + )\ + $(eval all-clean-file += $(ar)) \ +) + +# link several *.o files into a static libary +# $1: sources (*.o) +# $2: dst (xyz.a) +ar_cmd = ar crsD $(2) $(1) + +# print line used to ar object files +ifeq ($(V),1) +ar_print_cmd = echo $(call protect_quote,$(call ar_cmd,$1,$2)) +else +ar_print_cmd = echo " AR $(2)" +endif + +all-clean-file += $(all-ar) diff --git a/mk/ecoli-clean-rules.mk b/mk/ecoli-clean-rules.mk new file mode 100644 index 0000000..7c5113d --- /dev/null +++ b/mk/ecoli-clean-rules.mk @@ -0,0 +1,33 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +.PHONY: _ecoli_clean +_ecoli_clean: $(all-clean-target) FORCE + @$(call clean_print_cmd,$(all-clean-file) $(call depfile,$(all-clean-file)) \ + $(call cmdfile,$(all-clean-file))) && \ + $(call clean_cmd,$(all-clean-file) $(call depfile,$(all-clean-file)) \ + $(call cmdfile,$(all-clean-file))) diff --git a/mk/ecoli-clean-vars.mk b/mk/ecoli-clean-vars.mk new file mode 100644 index 0000000..53f732e --- /dev/null +++ b/mk/ecoli-clean-vars.mk @@ -0,0 +1,37 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# remove files +# $1: files +clean_cmd = rm -rf $(1) + +# print line used to clean files +ifeq ($(V),1) +clean_print_cmd = echo $(call protect_quote,$(call clean_cmd,$1)) +else +clean_print_cmd = echo " CLEAN $(CURDIR)" +endif diff --git a/mk/ecoli-copy-rules.mk b/mk/ecoli-copy-rules.mk new file mode 100644 index 0000000..6602a9e --- /dev/null +++ b/mk/ecoli-copy-rules.mk @@ -0,0 +1,55 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# dump some infos if debug is enabled +ifeq ($(D),1) +$(call disp_list,------ all-copy,$(all-copy)) +$(foreach copy,$(all-copy),\ + $(info,out-$(copy): $(out-$(copy))) \ + $(call disp_list,pre-$(copy),$(pre-$(copy))) \ +) +endif + +# include dependencies and commands files if they exist +$(foreach copy,$(all-copy),\ + $(eval -include $(call depfile,$(copy))) \ + $(eval -include $(call cmdfile,$(copy))) \ +) + +# remove duplicates +filtered-all-copy := $(sort $(all-copy)) + +# convert format of executable +$(filtered-all-copy): $$(pre-$$@) $$(wildcard $$(dep-$$@)) FORCE + @[ -d $(dir $@) ] || mkdir -p $(dir $@) + @$(call display_deps,$(pre-$(@)),$@,\ + $(call copy_cmd,$(pre-$(@)),$@),$?) + @$(if $(call check_deps,$@,$(call copy_cmd,$(pre-$(@)),$@),$?),\ + $(call copy_print_cmd,$(pre-$(@)),$@) && \ + $(call copy_cmd,$(pre-$(@)),$@) && \ + $(call save_cmd,$(call copy_cmd,$(pre-$(@)),$@),$@) && \ + $(call create_empty_depfile,$@)) diff --git a/mk/ecoli-copy-vars.mk b/mk/ecoli-copy-vars.mk new file mode 100644 index 0000000..677274e --- /dev/null +++ b/mk/ecoli-copy-vars.mk @@ -0,0 +1,74 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# copy a file +# copy-y-$(copy) is provided by the user +# $(copy) is the path of the directory containing the destination +# files, and the variable contains the path of the files to copy. Several +# copy-y-$(copy) can be present. + +# list all path requested by user +_all-copy := $(patsubst copy-y-%,%,$(filter copy-y-%,$(.VARIABLES))) +all-copy := + +# for each copy, create the following variables: +# out-$(copy) = output path of the executable +# pre-$(copy) = list of prerequisites for this executable +# We also add the files in $(all-copy). +$(foreach copy,$(_all-copy),\ + $(if $(notdir $(copy)), \ + $(if $(call compare,$(words $(copy-y-$(copy))),1), \ + $(error "only one source file is allowed in copy-y-$(copy)")) \ + $(eval dst := $(dir $(copy))$(notdir $(copy-y-$(copy)))) \ + $(eval out-$(copy) := $(dir $(copy))) \ + $(eval pre-$(copy) := $(copy-y-$(copy))) \ + $(eval all-copy += $(dst)) \ + , \ + $(foreach src,$(copy-y-$(copy)),\ + $(eval dst := $(copy)$(notdir $(src))) \ + $(eval out-$(copy) := $(copy)) \ + $(eval pre-$(dst) := $(src)) \ + $(eval all-copy += $(dst)) \ + ) \ + ) \ +) + +# add them to the list of targets and clean +all-targets += $(all-copy) +all-clean-file += $(all-copy) + +# convert format of executable from elf to ihex +# $1: source executable (elf) +# $2: destination file +copy_cmd = $(CP) $(1) $(2) + +# print line used to convert executable format +ifeq ($(V),1) +copy_print_cmd = echo $(call protect_quote,$(call copy_cmd,$1,$2)) +else +copy_print_cmd = echo " COPY $(2)" +endif diff --git a/mk/ecoli-exe-rules.mk b/mk/ecoli-exe-rules.mk new file mode 100644 index 0000000..a1a5c42 --- /dev/null +++ b/mk/ecoli-exe-rules.mk @@ -0,0 +1,55 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# dump some infos if debug is enabled +ifeq ($(D),1) +$(call disp_list,------ all-exe,$(all-exe)) +$(foreach exe,$(all-exe),\ + $(info,out-$(exe): $(out-$(exe))) \ + $(call disp_list,pre-$(exe),$(pre-$(exe))) \ +) +endif + +# include dependencies and commands files if they exist +$(foreach exe,$(all-exe),\ + $(eval -include $(call depfile,$(exe))) \ + $(eval -include $(call cmdfile,$(exe))) \ +) + +# remove duplicates +filtered-all-exe := $(sort $(all-exe)) + +# link several objects files into one executable +$(filtered-all-exe): $$(pre-$$@) $$(wildcard $$(dep-$$@)) FORCE + @[ -d $(dir $@) ] || mkdir -p $(dir $@) + @$(call display_deps,$(pre-$(@)),$@,\ + $(call link_cmd,$(pre-$(@)),$@),$?) + @$(if $(call check_deps,$@,$(call link_cmd,$(pre-$(@)),$@),$?),\ + $(call link_print_cmd,$(pre-$(@)),$@) && \ + $(call link_cmd,$(pre-$(@)),$@) && \ + $(call save_cmd,$(call link_cmd,$(pre-$(@)),$@),$@) && \ + $(call create_empty_depfile,$@)) diff --git a/mk/ecoli-exe-vars.mk b/mk/ecoli-exe-vars.mk new file mode 100644 index 0000000..f980be4 --- /dev/null +++ b/mk/ecoli-exe-vars.mk @@ -0,0 +1,79 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# exe-y-$(exe) is provided by the user +# $(exe) is the path of the binary, and the variable contains +# the list of sources. Several exe-y-$(exe) can be present. + +# list all exe builds requested by user +all-exe := $(patsubst exe-y-%,%,$(filter exe-y-%,$(.VARIABLES))) + +# add them to the list of targets +all-targets += $(all-exe) + +# for each exe, create the following variables: +# out-$(exe) = output path of the executable +# pre-$(exe) = list of prerequisites for this executable +# Some source files need intermediate objects, we define these variables +# for them too, and add them in a list: $(all-iobj). +# Last, we add the generated files in $(all-clean-file). +$(foreach exe,$(all-exe),\ + $(eval out-$(exe) := $(dir $(exe))) \ + $(eval pre-$(exe) := ) \ + $(foreach src,$(exe-y-$(exe)), \ + $(if $(call is_cc_source,$(src)), \ + $(eval iobj := $(call src2iobj,$(src),$(out-$(exe)))) \ + $(eval pre-$(iobj) := $(src)) \ + $(eval all-iobj += $(iobj)) \ + $(eval all-clean-file += $(iobj)) \ + $(eval pre-$(exe) += $(iobj)) \ + , \ + $(if $(call is_obj_source,$(src)),\ + $(eval pre-$(exe) += $(src)) \ + , \ + $(if $(call is_alib_source,$(src)),\ + $(eval pre-$(exe) += $(src)) \ + , \ + $(error "unsupported source format: $(src)")))) \ + )\ + $(eval all-clean-file += $(exe)) \ +) + +# link several *.o files into a exeary +# $1: sources (*.o) (*.a) +# $2: dst (xyz.o too) +link_cmd = $(CC) $(LDFLAGS) $(ldflags-$(2)) -o $(2) $(filter %.o,$(1)) \ + $(filter %.a,$(1)) $(LDLIBS) $(ldlibs-$(2)) + +# print line used to link object files +ifeq ($(V),1) +link_print_cmd = echo $(call protect_quote,$(call link_cmd,$1,$2)) +else +link_print_cmd = echo " EXE $(2)" +endif + +all-clean-file += $(all-exe) diff --git a/mk/ecoli-obj-rules.mk b/mk/ecoli-obj-rules.mk new file mode 100644 index 0000000..af208e4 --- /dev/null +++ b/mk/ecoli-obj-rules.mk @@ -0,0 +1,83 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# dump some infos if debug is enabled +ifeq ($(D),1) +$(call disp_list,------ all-obj,$(all-obj)) +$(foreach obj,$(all-obj),\ + $(info,out-$(obj): $(out-$(obj))) \ + $(call disp_list,pre-$(obj),$(pre-$(obj))) \ +) +$(call disp_list,------ all-iobj,$(all-iobj)) +$(foreach iobj,$(all-iobj),\ + $(call disp_list,pre-$(iobj),$(pre-$(iobj))) \ +) +endif + +# if a generated file has the same name than a user target, +# generate an error +conflicts := $(filter $(all-iobj),$(all-targets)) +$(if $(conflicts), \ + $(error Intermediate file has the same names than user targets:\ + $(conflicts))) + +# include dependencies and commands files if they exist +$(foreach obj,$(all-obj),\ + $(eval -include $(call depfile,$(obj))) \ + $(eval -include $(call cmdfile,$(obj))) \ +) +$(foreach iobj,$(all-iobj),\ + $(eval -include $(call depfile,$(iobj))) \ + $(eval -include $(call cmdfile,$(iobj))) \ +) + +# remove duplicates +filtered-all-iobj := $(sort $(all-iobj)) + +# convert source files to intermediate object file +$(filtered-all-iobj): $$(pre-$$@) $$(wildcard $$(dep-$$@)) FORCE + @[ -d $(dir $@) ] || mkdir -p $(dir $@) + @$(call display_deps,$(pre-$(@)),$@,$(call compile_cmd,$(pre-$(@)),$@),$?) + @$(if $(call check_deps,$@,$(call compile_cmd,$(pre-$(@)),$@),$?),\ + $(call compile_print_cmd,$(pre-$(@)),$@) && \ + $(call compile_cmd,$(pre-$(@)),$@) && \ + $(call save_cmd,$(call compile_cmd,$(pre-$(@)),$@),$@) && \ + $(call obj-fixdep,$@)) + +# remove duplicates +filtered-all-obj := $(sort $(all-obj)) + +# combine several objects files to one +$(filtered-all-obj): $$(pre-$$@) $$(wildcard $$(dep-$$@)) FORCE + @[ -d $(dir $@) ] || mkdir -p $(dir $@) + @$(call display_deps,$(pre-$(@)),$@,\ + $(call combine_cmd,$(pre-$(@)),$@),$?) + @$(if $(call check_deps,$@,$(call combine_cmd,$(pre-$(@)),$@),$?),\ + $(call combine_print_cmd,$(pre-$(@)),$@) && \ + $(call combine_cmd,$(pre-$(@)),$@) && \ + $(call save_cmd,$(call combine_cmd,$(pre-$(@)),$@),$@) && \ + $(call create_empty_depfile,$@)) diff --git a/mk/ecoli-obj-vars.mk b/mk/ecoli-obj-vars.mk new file mode 100644 index 0000000..8bd9101 --- /dev/null +++ b/mk/ecoli-obj-vars.mk @@ -0,0 +1,124 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# obj-y-$(obj) is provided by the user +# $(obj) is the path of the object, and the variable contains +# the list of sources. Several obj-y-$(obj) can be present. + +# list all object builds requested by user +all-obj := $(patsubst obj-y-%,%,$(filter obj-y-%,$(.VARIABLES))) + +# add them to the list of targets +all-targets += $(all-obj) + +# convert source path to intermediate object path, and filter +# objects from sources +# $1: list of source paths +# $2: output directory (including trailing slash) +# return: list of intermediate object paths +src2iobj = $(addprefix $(filter-out ./,$(2)),$(notdir $(strip \ + $(patsubst %.c,%.o,\ + $(patsubst %.s,%.o,\ + $(filter-out %.o,$(1))))))) + +# return the file if it matches a extension that is built with cc +# $1: source file +is_cc_source = $(filter %.c %.s %S,$(1)) + +# return the file if it's already an object file: in this case no +# intermediate object is needed +# $1: source file +is_obj_source = $(filter %.o,$(1)) + +# return the file if it's a static library +# $1: source file +is_alib_source = $(filter %.a,$(1)) + +# for each obj, create the following variables: +# out-$(obj) = output path of the object +# pre-$(obj) = list of prerequisites for this object +# Some source files need intermediate objects, we define these variables +# for them too, and add them in a list: $(all-iobj). +# Last, we add the generated files in $(all-clean-file). +$(foreach obj,$(all-obj),\ + $(eval out-$(obj) := $(dir $(obj))) \ + $(eval pre-$(obj) := ) \ + $(foreach src,$(obj-y-$(obj)), \ + $(if $(call is_cc_source,$(src)), \ + $(eval iobj := $(call src2iobj,$(src),$(out-$(obj)))) \ + $(eval pre-$(iobj) := $(src)) \ + $(eval all-iobj += $(iobj)) \ + $(eval all-clean-file += $(iobj)) \ + $(eval pre-$(obj) += $(iobj)) \ + , \ + $(if $(call is_obj_source,$(src)),\ + $(eval pre-$(obj) += $(src)) \ + , \ + $(error "unsupported source format: $(src)"))) \ + )\ + $(eval all-clean-file += $(obj)) \ +) + +# fix the format of .o.d.tmp (generated by gcc) to a .o.d that defines +# dependencies as makefile variables +# $1: object file (.o) +obj-fixdep = if [ -f $(call file2tmpdep,$(1)) ]; then\ + echo -n "dep-$(1) = " > $(call depfile,$(1)) && \ + sed 's,^[^ ][^:]*: ,,' $(call file2tmpdep,$(1)) >> $(call depfile,$(1)) && \ + rm -f $(call file2tmpdep,$(1)); \ + else \ + $(call create_empty_depfile,$(1)); \ + fi + +# compile a file +# $1: sources +# $2: dst +compile_cmd = $(CC) -Wp,-MD,$(call file2tmpdep,$(2)) \ + $(CPPFLAGS) $(cppflags-$(2)) \ + $(CFLAGS) $(cflags-$(2)) \ + -c -o $2 $1 + +# print line used to compile a file +ifeq ($(V),1) +compile_print_cmd = echo $(call protect_quote,$(call compile_cmd,$1,$2)) +else +compile_print_cmd = echo " CC $(2)" +endif + +# combine several *.o files into one +# $1: sources (*.o) +# $2: dst (xyz.o too) +combine_cmd = $(LD) -r $(1) -o $(2) + +# print line used to combine object files +ifeq ($(V),1) +combine_print_cmd = echo $(call protect_quote,$(call combine_cmd,$1,$2)) +else +combine_print_cmd = echo " LD $(2)" +endif + +all-clean-file += $(all-obj) diff --git a/mk/ecoli-objcopy-rules.mk b/mk/ecoli-objcopy-rules.mk new file mode 100644 index 0000000..86a7cb6 --- /dev/null +++ b/mk/ecoli-objcopy-rules.mk @@ -0,0 +1,74 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# dump some infos if debug is enabled +ifeq ($(D),1) +$(call disp_list,------ all-objcopy-hex,$(all-objcopy-hex)) +$(foreach objcopy,$(all-objcopy-hex),\ + $(info,out-$(objcopy): $(out-$(objcopy))) \ + $(call disp_list,pre-$(objcopy),$(pre-$(objcopy))) \ +) +$(call disp_list,------ all-objcopy-bin,$(all-objcopy-bin)) +$(foreach objcopy,$(all-objcopy-bin),\ + $(info,out-$(objcopy): $(out-$(objcopy))) \ + $(call disp_list,pre-$(objcopy),$(pre-$(objcopy))) \ +) +endif + +# include dependencies and commands files if they exist +$(foreach objcopy,$(all-objcopy-hex) $(all-objcopy-bin),\ + $(eval -include $(call depfile,$(objcopy))) \ + $(eval -include $(call cmdfile,$(objcopy))) \ +) + +# remove duplicates +filtered-all-objcopy-hex := $(sort $(all-objcopy-hex)) + +# convert format of executable +$(filtered-all-objcopy-hex): $$(pre-$$@) $$(wildcard $$(dep-$$@)) FORCE + @[ -d $(dir $@) ] || mkdir -p $(dir $@) + @$(call display_deps,$(pre-$(@)),$@,\ + $(call objcopy_hex_cmd,$(pre-$(@)),$@),$?) + @$(if $(call check_deps,$@,$(call objcopy_hex_cmd,$(pre-$(@)),$@),$?),\ + $(call objcopy_print_cmd,$(pre-$(@)),$@) && \ + $(call objcopy_hex_cmd,$(pre-$(@)),$@) && \ + $(call save_cmd,$(call objcopy_hex_cmd,$(pre-$(@)),$@),$@) && \ + $(call create_empty_depfile,$@)) + +# remove duplicates +filtered-all-objcopy-bin := $(sort $(all-objcopy-bin)) + +# convert format of executable +$(filtered-all-objcopy-bin): $$(pre-$$@) $$(wildcard $$(dep-$$@)) FORCE + @[ -d $(dir $@) ] || mkdir -p $(dir $@) + @$(call display_deps,$(pre-$(@)),$@,\ + $(call objcopy_bin_cmd,$(pre-$(@)),$@),$?) + @$(if $(call check_deps,$@,$(call objcopy_bin_cmd,$(pre-$(@)),$@),$?),\ + $(call objcopy_print_cmd,$(pre-$(@)),$@) && \ + $(call objcopy_bin_cmd,$(pre-$(@)),$@) && \ + $(call save_cmd,$(call objcopy_bin_cmd,$(pre-$(@)),$@),$@) && \ + $(call create_empty_depfile,$@)) diff --git a/mk/ecoli-objcopy-vars.mk b/mk/ecoli-objcopy-vars.mk new file mode 100644 index 0000000..d515d02 --- /dev/null +++ b/mk/ecoli-objcopy-vars.mk @@ -0,0 +1,89 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# objcopy changes the format of a binary +# objcopy-hex-y-$(objcopy), objcopy-bin-y-$(objcopy) are provided by the user +# $(objcopy) is the path of the binary, and the variable contains +# the path to the elf. Several objcopy-y-$(objcopy) can be present. + +# list all executable builds requested by user +all-objcopy-hex := $(patsubst objcopy-hex-y-%,%,$(filter objcopy-hex-y-%,$(.VARIABLES))) +all-objcopy-bin := $(patsubst objcopy-bin-y-%,%,$(filter objcopy-bin-y-%,$(.VARIABLES))) + +# add them to the list of targets +all-targets += $(all-objcopy-hex) $(all-objcopy-bin) + +# for each objcopy, create the following variables: +# out-$(objcopy) = output path of the executable +# pre-$(objcopy) = list of prerequisites for this executable +# We also add the generated files in $(all-clean-file). +$(foreach objcopy,$(all-objcopy-hex),\ + $(if $(call compare,$(words $(objcopy-hex-y-$(objcopy))),1),\ + $(error "only one source file is allowed in objcopy-hex-y-$(objcopy)")) \ + $(eval out-$(objcopy) := $(dir $(objcopy))) \ + $(eval pre-$(objcopy) := $(objcopy-hex-y-$(objcopy))) \ + $(eval all-clean-file += $(objcopy)) \ +) + +# for each objcopy, create the following variables: +# out-$(objcopy) = output path of the executable +# pre-$(objcopy) = list of prerequisites for this executable +# We also add the generated files in $(all-clean-file). +$(foreach objcopy,$(all-objcopy-bin),\ + $(if $(call compare,$(words $(objcopy-bin-y-$(objcopy))),1),\ + $(error "only one source file is allowed in objcopy-bin-y-$(objcopy)")) \ + $(eval out-$(objcopy) := $(dir $(objcopy))) \ + $(eval pre-$(objcopy) := $(objcopy-bin-y-$(objcopy))) \ + $(eval all-clean-file += $(objcopy)) \ +) + +# convert format of executable from elf to ihex +# $1: source executable (elf) +# $2: destination file +objcopy_hex_cmd = $(OBJCOPY) -O ihex $(1) $(2) + +# print line used to convert executable format +ifeq ($(V),1) +objcopy_print_cmd = echo $(call protect_quote,$(call objcopy_hex_cmd,$1,$2)) +else +objcopy_print_cmd = echo " OBJCOPY $(2)" +endif + +# convert format of executable from elf to binary +# $1: source executable (elf) +# $2: destination file +objcopy_bin_cmd = $(OBJCOPY) -O binary $(1) $(2) + +# print line used to convert executable format +ifeq ($(V),1) +objcopy_print_cmd = echo $(call protect_quote,$(call objcopy_bin_cmd,$1,$2)) +else +objcopy_print_cmd = echo " OBJCOPY $(2)" +endif + +# XXX dup ? +all-clean-file += $(all-objcopy-hex) $(all-objcopy-bin) diff --git a/mk/ecoli-post.mk b/mk/ecoli-post.mk new file mode 100644 index 0000000..e51566e --- /dev/null +++ b/mk/ecoli-post.mk @@ -0,0 +1,108 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# ---- variables that must be defined: +# +# ECOLI: path to ecoli root +# +# ---- variable that can be defined anywhere +# +# CROSS: prefix of the toolchain +# CP, LN, GAWK, GREP: coreutils tools +# CC, CPP, AR, LD, OBJCOPY, OBJDUMP, STRIP: compilers/binutils +# +# ---- variable that can be defined by Makefile: +# +# obj-y-$(path) +# exe-y-$(path) +# ar-y-$(path) +# shlib-y-$(path) +# copy-y-$(path) +# slink-y-$(path) +# objcopy-y-$(path) +# subdir-y +# +# CPPFLAGS, CFLAGS, LDFLAGS, LDLIBS: global flags +# cflags-$(path), cppflags-$(path), ldflags-$(path), ldlibs-$(path): per +# file flags +# mkflags-$(path): flags for subdirectories +# +# ---- variables that can be defined on the command line: +# +# EXTRA_CPPFLAGS, EXTRA_CFLAGS, EXTRA_LDFLAGS, EXTRA_LDLIBS: global +# extra flags +# extra-cflags-$(path), extra-cppflags-$(path): per object extra flags + +ifeq ($(ECOLI),) +$(error ECOLI environment variable is not defined) +endif + +# list of targets asked by user +all-targets := +# list of files generated +all-clean-file := + +# usual internal variables: +# out-$(file) = output path of a generated file +# pre-$(file) = list of files needed to generate $(file) +# all-type = list of targets for this type + +include $(ECOLI)/mk/ecoli-obj-vars.mk +include $(ECOLI)/mk/ecoli-exe-vars.mk +include $(ECOLI)/mk/ecoli-ar-vars.mk +include $(ECOLI)/mk/ecoli-shlib-vars.mk +include $(ECOLI)/mk/ecoli-copy-vars.mk +include $(ECOLI)/mk/ecoli-slink-vars.mk +include $(ECOLI)/mk/ecoli-objcopy-vars.mk +include $(ECOLI)/mk/ecoli-subdir-vars.mk +# must stay at the end +include $(ECOLI)/mk/ecoli-clean-vars.mk + +# dump the list of targets +ifeq ($(D),1) +$(call disp_list,------ all-targets,$(all-targets)) +endif + +# first rule (default) +.PHONY: _ecoli_all +_ecoli_all: $(all-targets) + +# the includes below require second expansion +.SECONDEXPANSION: + +include $(ECOLI)/mk/ecoli-obj-rules.mk +include $(ECOLI)/mk/ecoli-exe-rules.mk +include $(ECOLI)/mk/ecoli-ar-rules.mk +include $(ECOLI)/mk/ecoli-shlib-rules.mk +include $(ECOLI)/mk/ecoli-copy-rules.mk +include $(ECOLI)/mk/ecoli-slink-rules.mk +include $(ECOLI)/mk/ecoli-objcopy-rules.mk +include $(ECOLI)/mk/ecoli-subdir-rules.mk +include $(ECOLI)/mk/ecoli-clean-rules.mk + +.PHONY: FORCE +FORCE: diff --git a/mk/ecoli-pre.mk b/mk/ecoli-pre.mk new file mode 100644 index 0000000..9cc59e9 --- /dev/null +++ b/mk/ecoli-pre.mk @@ -0,0 +1,42 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# ---- variables that must be defined: +# +# ECOLI: path to ecoli root +# + +ifeq ($(ECOLI),) +$(error ECOLI environment variable is not defined) +endif + +MAKEFLAGS += --no-print-directory + +include $(ECOLI)/mk/ecoli-tools.mk + +include $(ECOLI)/mk/ecoli-vars.mk + diff --git a/mk/ecoli-shlib-rules.mk b/mk/ecoli-shlib-rules.mk new file mode 100644 index 0000000..1a131cc --- /dev/null +++ b/mk/ecoli-shlib-rules.mk @@ -0,0 +1,55 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# dump some infos if debug is enabled +ifeq ($(D),1) +$(call disp_list,------ all-shlib,$(all-shlib)) +$(foreach shlib,$(all-shlib),\ + $(info,out-$(shlib): $(out-$(shlib))) \ + $(call disp_list,pre-$(shlib),$(pre-$(shlib))) \ +) +endif + +# include dependencies and commands files if they exist +$(foreach shlib,$(all-shlib),\ + $(eval -include $(call depfile,$(shlib))) \ + $(eval -include $(call cmdfile,$(shlib))) \ +) + +# remove duplicates +filtered-all-shlib := $(sort $(all-shlib)) + +# link several objects files into one shared object +$(filtered-all-shlib): $$(pre-$$@) $$(wildcard $$(dep-$$@)) FORCE + @[ -d $(dir $@) ] || mkdir -p $(dir $@) + @$(call display_deps,$(pre-$(@)),$@,\ + $(call shlib_cmd,$(pre-$(@)),$@),$?) + @$(if $(call check_deps,$@,$(call shlib_cmd,$(pre-$(@)),$@),$?),\ + $(call shlib_print_cmd,$(pre-$(@)),$@) && \ + $(call shlib_cmd,$(pre-$(@)),$@) && \ + $(call save_cmd,$(call shlib_cmd,$(pre-$(@)),$@),$@) && \ + $(call create_empty_depfile,$@)) diff --git a/mk/ecoli-shlib-vars.mk b/mk/ecoli-shlib-vars.mk new file mode 100644 index 0000000..7906510 --- /dev/null +++ b/mk/ecoli-shlib-vars.mk @@ -0,0 +1,76 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# shlib-y-$(shlib) is provided by the user +# $(shlib) is the path of the shared library, and the variable +# contains the list of sources. Several shlib-y-$(shlib) can be +# present. + +# list all shlib builds requested by user +all-shlib := $(patsubst shlib-y-%,%,$(filter shlib-y-%,$(.VARIABLES))) + +# add them to the list of targets +all-targets += $(all-shlib) + +# for each shlib, create the following variables: +# out-$(shlib) = output path of the shlibcutable +# pre-$(shlib) = list of prerequisites for this shlibcutable +# Some source files need intermediate objects, we define these variables +# for them too, and add them in a list: $(all-iobj). +# Last, we add the generated files in $(all-clean-file). +$(foreach shlib,$(all-shlib),\ + $(eval out-$(shlib) := $(dir $(shlib))) \ + $(eval pre-$(shlib) := ) \ + $(foreach src,$(shlib-y-$(shlib)), \ + $(if $(call is_cc_source,$(src)), \ + $(eval iobj := $(call src2iobj,$(src),$(out-$(shlib)))) \ + $(eval pre-$(iobj) := $(src)) \ + $(eval all-iobj += $(iobj)) \ + $(eval all-clean-file += $(iobj)) \ + $(eval pre-$(shlib) += $(iobj)) \ + , \ + $(if $(call is_obj_source,$(src)),\ + $(eval pre-$(shlib) += $(src)) \ + , \ + $(error "unsupported source format: $(src)"))) \ + )\ + $(eval all-clean-file += $(shlib)) \ +) + +# link several *.o files into a shared libary +# $1: sources (*.o) +# $2: dst (xyz.so) +shlib_cmd = $(CC) $(LDFLAGS) $(ldflags-$(2)) -shared -o $(2) $(1) + +# print line used to shlib object files +ifeq ($(V),1) +shlib_print_cmd = echo $(call protect_quote,$(call shlib_cmd,$1,$2)) +else +shlib_print_cmd = echo " SHLIB $(2)" +endif + +all-clean-file += $(all-shlib) diff --git a/mk/ecoli-slink-rules.mk b/mk/ecoli-slink-rules.mk new file mode 100644 index 0000000..bea3aad --- /dev/null +++ b/mk/ecoli-slink-rules.mk @@ -0,0 +1,55 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# dump some infos if debug is enabled +ifeq ($(D),1) +$(call disp_list,------ all-slink,$(all-slink)) +$(foreach slink,$(all-slink),\ + $(info,out-$(slink): $(out-$(slink))) \ + $(call disp_list,pre-$(slink),$(pre-$(slink))) \ +) +endif + +# include dependencies and commands files if they exist +$(foreach slink,$(all-slink),\ + $(eval -include $(call depfile,$(slink))) \ + $(eval -include $(call cmdfile,$(slink))) \ +) + +# remove duplicates +filtered-all-slink := $(sort $(all-slink)) + +# convert format of executable +$(filtered-all-slink): $$(pre-$$@) $$(wildcard $$(dep-$$@)) FORCE + @[ -d $(dir $@) ] || mkdir -p $(dir $@) + @$(call display_deps,$(pre-$(@)),$@,\ + $(call slink_cmd,$(pre-$(@)),$@),$?) + @$(if $(call check_deps,$@,$(call slink_cmd,$(pre-$(@)),$@),$?),\ + $(call slink_print_cmd,$(pre-$(@)),$@) && \ + $(call slink_cmd,$(pre-$(@)),$@) && \ + $(call save_cmd,$(call slink_cmd,$(pre-$(@)),$@),$@) && \ + $(call create_empty_depfile,$@)) diff --git a/mk/ecoli-slink-vars.mk b/mk/ecoli-slink-vars.mk new file mode 100644 index 0000000..428cb25 --- /dev/null +++ b/mk/ecoli-slink-vars.mk @@ -0,0 +1,74 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# create a symbolic link of a file +# slink-y-$(slink) is provided by the user +# $(slink) is the path of the directory containing the destination +# files, and the variable contains the path of the files to linked. Several +# slink-y-$(slink) can be present. + +# list all path requested by user +_all-slink := $(patsubst slink-y-%,%,$(filter slink-y-%,$(.VARIABLES))) +all-slink := + +# for each slink, create the following variables: +# out-$(slink) = output path of the executable +# pre-$(slink) = list of prerequisites for this executable +# We also add the files in $(all-slink). +$(foreach slink,$(_all-slink),\ + $(if $(notdir $(slink)), \ + $(if $(call compare,$(words $(slink-y-$(slink))),1), \ + $(error "only one source file is allowed in slink-y-$(slink)")) \ + $(eval dst := $(dir $(slink))$(notdir $(slink-y-$(slink)))) \ + $(eval out-$(slink) := $(dir $(slink))) \ + $(eval pre-$(slink) := $(slink-y-$(slink))) \ + $(eval all-slink += $(dst)) \ + , \ + $(foreach src,$(slink-y-$(slink)),\ + $(eval dst := $(slink)$(notdir $(src))) \ + $(eval out-$(slink) := $(slink)) \ + $(eval pre-$(dst) := $(src)) \ + $(eval all-slink += $(dst)) \ + ) \ + ) \ +) + +# add them to the list of targets and clean +all-targets += $(all-slink) +all-clean-file += $(all-slink) + +# convert format of executable from elf to ihex +# $1: source executable (elf) +# $2: destination file +slink_cmd = $(LN) -nsf $(abspath $(1)) $(2) + +# print line used to convert executable format +ifeq ($(V),1) +slink_print_cmd = echo $(call protect_quote,$(call slink_cmd,$1,$2)) +else +slink_print_cmd = echo " SLINK $(2)" +endif diff --git a/mk/ecoli-subdir-rules.mk b/mk/ecoli-subdir-rules.mk new file mode 100644 index 0000000..aae82db --- /dev/null +++ b/mk/ecoli-subdir-rules.mk @@ -0,0 +1,30 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +.PHONY: $(subdir-y) +$(subdir-y): FORCE + $(Q)$(MAKE) -C $(@) $(mkflags-$(@)) $(MAKECMDGOALS) diff --git a/mk/ecoli-subdir-vars.mk b/mk/ecoli-subdir-vars.mk new file mode 100644 index 0000000..14e4ee1 --- /dev/null +++ b/mk/ecoli-subdir-vars.mk @@ -0,0 +1,33 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# subdir-y is provided by the user +# it contains the list of directory to build + +# add them to the list of targets +all-targets += $(subdir-y) +all-clean-target += $(subdir-y) diff --git a/mk/ecoli-tools.mk b/mk/ecoli-tools.mk new file mode 100644 index 0000000..484262b --- /dev/null +++ b/mk/ecoli-tools.mk @@ -0,0 +1,159 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +empty:= +space:= $(empty) $(empty) +indent:= $(space)$(space) + +# define a newline char, useful for debugging with $(info) +define newline + + +endef + +# $(prefix shell commands with $(Q) to silent them, except if V=1 +Q=@ +ifeq ("$(V)-$(origin V)", "1-command line") +Q= +endif + +# set variable $1 to $2 if the variable has an implicit value or +# is not defined +# $1 variable name +# $2 new variable content +set_default = $(if \ + $(call not,$(or \ + $(compare $(origin $(1)),default), \ + $(compare $(origin $(1)),undefined) \ + )),\ + $(eval $(1) = $(2)) \ +) + +# display a list +# $1 title +# $2 list +disp_list = $(info $(1)$(newline)\ + $(addsuffix $(newline),$(addprefix $(space),$(2)))) + +# add a dot in front of the file name +# $1 list of paths +# return: full paths with files prefixed by a dot +dotfile = $(strip $(foreach f,$(1),\ + $(join $(dir $f),.$(notdir $f)))) + +# convert source/obj files into dot-dep filename +# $1 list of paths +# return: full paths with files prefixed by a dot and suffixed with .d +depfile = $(strip $(call dotfile,$(addsuffix .d,$(1)))) + +# convert source/obj files into dot-dep filename +# $1 list of paths +# return: full paths with files prefixed by a dot and suffixed with .d.tmp +file2tmpdep = $(strip $(call dotfile,$(addsuffix .d.tmp,$(1)))) + +# convert source/obj files into dot-cmd filename +# $1 list of paths +# return: full paths with files prefixed by a dot and suffixed with .cmd +cmdfile = $(strip $(call dotfile,$(addsuffix .cmd,$(1)))) + +# add a \ before each quote +protect_quote = $(subst ','\'',$(1)) +#'# editor syntax highlight fix + +# return an non-empty string if $1 is empty, and vice versa +# $1 a string +not = $(if $1,,true) + +# return 1 if parameter is a non-empty string, else 0 +boolean = $(if $1,1,0) + +# return an empty string if string are equal +compare = $(strip $(subst $(1),,$(2)) $(subst $(2),,$(1))) + +# return a non-empty string if a file does not exist +# $1: file +file_missing = $(call compare,$(wildcard $1),$1) + +# return a non-empty string if cmdline changed +# $1: file to be built +# $2: the command to build it +cmdline_changed = $(call compare,$(strip $(cmd-$(1))),$(strip $(2))) + +# return an non-empty string if the .d file does not exist +# $1: the dep file (.d) +depfile_missing = $(call compare,$(wildcard $(1)),$(1)) + +# return a non-empty string if, according to dep-xyz variable, a file +# needed to build $1 does not exist. In this case we need to rebuild +# the file and the .d file. +# $1: file to be built +dep-missing = $(call compare,$(wildcard $(dep-$(1))),$(dep-$(1))) + +# return an empty string if no prereq is newer than target +# $1: list of prerequisites newer than target ($?) +dep-newer = $(strip $(filter-out FORCE,$(1))) + +# display why a file should be re-built +# $1: source files +# $2: dst file +# $3: build command +# $4: all prerequisites newer than target ($?) +ifeq ($(D),1) +display_deps = \ + echo -n "$1 -> $2 " ; \ + echo -n "file_missing=$(call boolean,$(call file_missing,$(2))) " ; \ + echo -n "cmdline_changed=$(call boolean,$(call cmdline_changed,$(2),$(3))) " ; \ + echo -n "depfile_missing=$(call boolean,$(call depfile_missing,$(call depfile,$(2)))) " ; \ + echo -n "dep-missing=$(call boolean,$(call dep-missing,$(2))) " ; \ + echo "dep-newer=$(call boolean,$(call dep-newer,$(4)))" +else +display_deps= +endif + +# return an empty string if a file should be rebuilt +# $1: dst file +# $2: build command +# $3: all prerequisites newer than target ($?) +check_deps = \ + $(or $(call file_missing,$(1)),\ + $(call cmdline_changed,$(1),$(2)),\ + $(call depfile_missing,$(call depfile,$(1))),\ + $(call dep-missing,$(1)),\ + $(call dep-newer,$(3))) + +# create a depfile (.d) with no additional deps +# $1: object file (.o) +create_empty_depfile = echo "dep-$(1) =" > $(call depfile,$(1)) + +# save a command in a file +# $1: command to build the file +# $2: name of the file +save_cmd = echo "cmd-$(2) = $(call protect_quote,$(1))" > $(call cmdfile,$(2)) + +# remove the FORCE target from the list of all prerequisites $+ +# no arguments, use $+ +prereq = $(filter-out FORCE,$(+)) diff --git a/mk/ecoli-vars.mk b/mk/ecoli-vars.mk new file mode 100644 index 0000000..79ece82 --- /dev/null +++ b/mk/ecoli-vars.mk @@ -0,0 +1,47 @@ +# +# Copyright 2015, Olivier MATZ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the University of California, Berkeley nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# core tools +CP ?= cp +LN ?= ln +GAWK ?= gawk +GREP ?= grep +# compiler and binutils, set_default overrides mk implicit value +# but not command line or standard variables +$(call set_default,CC,$(CROSS)gcc) +$(call set_default,CPP,$(CROSS)cpp) +$(call set_default,AR,$(CROSS)ar) +$(call set_default,LD,$(CROSS)ld) +$(call set_default,OBJCOPY,$(CROSS)objcopy) +$(call set_default,OBJDUMP,$(CROSS)objdump) +$(call set_default,STRIP,$(CROSS)strip) +HOSTCC ?= cc + +CFLAGS += $(EXTRA_CFLAGS) +CPPFLAGS += $(EXTRA_CPPFLAGS) +LDFLAGS += $(EXTRA_LDFLAGS) +LDLIBS += $(EXTRA_LDLIBS)