init
authorOlivier Matz <zer0@droids-corp.org>
Thu, 27 Oct 2016 15:59:44 +0000 (17:59 +0200)
committerOlivier Matz <zer0@droids-corp.org>
Thu, 27 Oct 2016 15:59:44 +0000 (17:59 +0200)
41 files changed:
lib/Makefile [new file with mode: 0644]
lib/build/test [new file with mode: 0755]
lib/ecoli_test.c [new file with mode: 0644]
lib/ecoli_test.h [new file with mode: 0644]
lib/ecoli_tk.c [new file with mode: 0644]
lib/ecoli_tk.h [new file with mode: 0644]
lib/ecoli_tk_empty.c [new file with mode: 0644]
lib/ecoli_tk_empty.h [new file with mode: 0644]
lib/ecoli_tk_int.c [new file with mode: 0644]
lib/ecoli_tk_int.h [new file with mode: 0644]
lib/ecoli_tk_or.c [new file with mode: 0644]
lib/ecoli_tk_or.h [new file with mode: 0644]
lib/ecoli_tk_seq.c [new file with mode: 0644]
lib/ecoli_tk_seq.h [new file with mode: 0644]
lib/ecoli_tk_space.c [new file with mode: 0644]
lib/ecoli_tk_space.h [new file with mode: 0644]
lib/ecoli_tk_str.c [new file with mode: 0644]
lib/ecoli_tk_str.h [new file with mode: 0644]
lib/main.c [new file with mode: 0644]
mk/ecoli-ar-rules.mk [new file with mode: 0644]
mk/ecoli-ar-vars.mk [new file with mode: 0644]
mk/ecoli-clean-rules.mk [new file with mode: 0644]
mk/ecoli-clean-vars.mk [new file with mode: 0644]
mk/ecoli-copy-rules.mk [new file with mode: 0644]
mk/ecoli-copy-vars.mk [new file with mode: 0644]
mk/ecoli-exe-rules.mk [new file with mode: 0644]
mk/ecoli-exe-vars.mk [new file with mode: 0644]
mk/ecoli-obj-rules.mk [new file with mode: 0644]
mk/ecoli-obj-vars.mk [new file with mode: 0644]
mk/ecoli-objcopy-rules.mk [new file with mode: 0644]
mk/ecoli-objcopy-vars.mk [new file with mode: 0644]
mk/ecoli-post.mk [new file with mode: 0644]
mk/ecoli-pre.mk [new file with mode: 0644]
mk/ecoli-shlib-rules.mk [new file with mode: 0644]
mk/ecoli-shlib-vars.mk [new file with mode: 0644]
mk/ecoli-slink-rules.mk [new file with mode: 0644]
mk/ecoli-slink-vars.mk [new file with mode: 0644]
mk/ecoli-subdir-rules.mk [new file with mode: 0644]
mk/ecoli-subdir-vars.mk [new file with mode: 0644]
mk/ecoli-tools.mk [new file with mode: 0644]
mk/ecoli-vars.mk [new file with mode: 0644]

diff --git a/lib/Makefile b/lib/Makefile
new file mode 100644 (file)
index 0000000..0ce853f
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# Copyright 2016, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (executable)
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 (file)
index 0000000..6b4a43f
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ecoli_test.h>
+#include <ecoli_tk.h>
+
+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 (file)
index 0000000..61d9950
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * 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 <sys/queue.h>
+
+#include <ecoli_tk.h>
+
+#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 (file)
index 0000000..7c5ac21
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <ecoli_tk.h>
+
+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 (file)
index 0000000..15be2be
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * 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 <sys/queue.h>
+#include <sys/types.h>
+
+#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 (file)
index 0000000..e8e98e1
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <ecoli_tk.h>
+#include <ecoli_tk_empty.h>
+
+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 (file)
index 0000000..4e22420
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * 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 <ecoli_tk.h>
+
+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 (file)
index 0000000..6bd4bfd
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <ecoli_tk.h>
+#include <ecoli_tk_int.h>
+#include <ecoli_test.h>
+
+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 (file)
index 0000000..e210279
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * 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 <ecoli_tk.h>
+
+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 (file)
index 0000000..dda2230
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdarg.h>
+
+#include <ecoli_tk.h>
+#include <ecoli_tk_or.h>
+#include <ecoli_tk_str.h>
+#include <ecoli_test.h>
+
+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 (file)
index 0000000..130ec4d
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * 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 <sys/queue.h>
+
+#include <ecoli_tk.h>
+
+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 (file)
index 0000000..38c633a
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdarg.h>
+
+#include <ecoli_tk.h>
+#include <ecoli_tk_seq.h>
+
+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 (file)
index 0000000..5c7bfed
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * 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 <sys/queue.h>
+
+#include <ecoli_tk.h>
+
+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 (file)
index 0000000..ed2ee31
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <ecoli_tk.h>
+#include <ecoli_tk_space.h>
+
+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 (file)
index 0000000..6327c8a
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * 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 <ecoli_tk.h>
+
+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 (file)
index 0000000..8152704
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <ecoli_test.h>
+#include <ecoli_tk.h>
+#include <ecoli_tk_str.h>
+
+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 (file)
index 0000000..e7c0759
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * 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 <ecoli_tk.h>
+
+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 (file)
index 0000000..54057b7
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include <ecoli_test.h>
+#include <ecoli_tk_str.h>
+#include <ecoli_tk_seq.h>
+#include <ecoli_tk_space.h>
+#include <ecoli_tk_or.h>
+
+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 (file)
index 0000000..4ad30cb
--- /dev/null
@@ -0,0 +1,55 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..7d2fab7
--- /dev/null
@@ -0,0 +1,75 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..7c5113d
--- /dev/null
@@ -0,0 +1,33 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..53f732e
--- /dev/null
@@ -0,0 +1,37 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..6602a9e
--- /dev/null
@@ -0,0 +1,55 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..677274e
--- /dev/null
@@ -0,0 +1,74 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..a1a5c42
--- /dev/null
@@ -0,0 +1,55 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..f980be4
--- /dev/null
@@ -0,0 +1,79 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..af208e4
--- /dev/null
@@ -0,0 +1,83 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..8bd9101
--- /dev/null
@@ -0,0 +1,124 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..86a7cb6
--- /dev/null
@@ -0,0 +1,74 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..d515d02
--- /dev/null
@@ -0,0 +1,89 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..e51566e
--- /dev/null
@@ -0,0 +1,108 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..9cc59e9
--- /dev/null
@@ -0,0 +1,42 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..1a131cc
--- /dev/null
@@ -0,0 +1,55 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..7906510
--- /dev/null
@@ -0,0 +1,76 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..bea3aad
--- /dev/null
@@ -0,0 +1,55 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..428cb25
--- /dev/null
@@ -0,0 +1,74 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..aae82db
--- /dev/null
@@ -0,0 +1,30 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..14e4ee1
--- /dev/null
@@ -0,0 +1,33 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..484262b
--- /dev/null
@@ -0,0 +1,159 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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 (file)
index 0000000..79ece82
--- /dev/null
@@ -0,0 +1,47 @@
+#
+# Copyright 2015, Olivier MATZ <zer0@droids-corp.org>
+#
+# 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)