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
+srcs += ecoli_malloc.c
shlib-y-$(O)libecoli.so := $(srcs)
exe-y-$(O)test = $(srcs) main.c
--- /dev/null
+/*
+ * 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 <ecoli_malloc.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+struct ec_malloc_handler ec_malloc_handler;
+
+int ec_malloc_register(ec_malloc_t usr_malloc, ec_free_t usr_free,
+ ec_realloc_t usr_realloc)
+{
+ if (usr_malloc == NULL || usr_free == NULL || usr_realloc == NULL)
+ return -1;
+
+ ec_malloc_handler.malloc = usr_malloc;
+ ec_malloc_handler.free = usr_free;
+ ec_malloc_handler.realloc = usr_realloc;
+
+ return 0;
+}
+
+void *__ec_malloc(size_t size)
+{
+ return ec_malloc_handler.malloc(size);
+}
+
+void __ec_free(void *ptr)
+{
+ ec_malloc_handler.free(ptr);
+}
+
+void *__ec_calloc(size_t nmemb, size_t size)
+{
+ void *ptr;
+ size_t total;
+
+ total = size * nmemb;
+ if (nmemb != 0 && size != (total / nmemb)) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ ptr = __ec_malloc(total);
+ if (ptr == NULL)
+ return NULL;
+
+ memset(ptr, 0, size);
+ return ptr;
+}
+
+void *__ec_realloc(void *ptr, size_t size)
+{
+ return ec_malloc_handler.realloc(ptr, size);
+}
+
+char *__ec_strdup(const char *s)
+{
+ size_t sz = strlen(s) + 1;
+ char *s2;
+
+ s2 = __ec_malloc(sz);
+ if (s2 == NULL)
+ return NULL;
+
+ memcpy(s2, s, sz);
+
+ return s2;
+}
+
+char *__ec_strndup(const char *s, size_t n)
+{
+ size_t sz = strnlen(s, n);
+ char *s2;
+
+ s2 = __ec_malloc(sz + 1);
+ if (s2 == NULL)
+ return NULL;
+
+ memcpy(s2, s, sz);
+ s2[sz] = '\0';
+
+ return s2;
+}
--- /dev/null
+/*
+ * 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_MALLOC_
+#define ECOLI_MALLOC_
+
+#include <sys/types.h>
+
+typedef void *(*ec_malloc_t)(size_t size);
+typedef void (*ec_free_t)(void *ptr);
+typedef void *(*ec_realloc_t)(void *ptr, size_t size);
+
+struct ec_malloc_handler {
+ ec_malloc_t malloc;
+ ec_free_t free;
+ ec_realloc_t realloc;
+};
+
+extern struct ec_malloc_handler ec_malloc_handler;
+
+int ec_malloc_register(ec_malloc_t usr_malloc, ec_free_t usr_free,
+ ec_realloc_t usr_realloc);
+
+/* internal */
+void *__ec_malloc(size_t size);
+void __ec_free(void *ptr);
+void *__ec_calloc(size_t nmemb, size_t size);
+void *__ec_realloc(void *ptr, size_t size);
+char *__ec_strdup(const char *s);
+char *__ec_strndup(const char *s, size_t n);
+
+/* we use macros here to ensure the file/line stay correct when
+ * debugging the standard malloc with valgrind */
+
+#define ec_malloc(sz) ({ \
+ void *ret_; \
+ if (ec_malloc_handler.malloc == NULL) \
+ ret_ = malloc(sz); \
+ else \
+ ret_ = __ec_malloc(sz); \
+ ret_; \
+ })
+
+#define ec_free(ptr) ({ \
+ if (ec_malloc_handler.free == NULL) \
+ free(ptr); \
+ else \
+ __ec_free(ptr); \
+ })
+
+#define ec_realloc(ptr, sz) ({ \
+ void *ret_; \
+ if (ec_malloc_handler.realloc == NULL) \
+ ret_ = realloc(ptr, sz); \
+ else \
+ ret_ = __ec_realloc(ptr, sz); \
+ ret_; \
+ })
+
+#define ec_calloc(n, sz) ({ \
+ void *ret_; \
+ if (ec_malloc_handler.malloc == NULL) \
+ ret_ = calloc(n, sz); \
+ else \
+ ret_ = __ec_calloc(n, sz); \
+ ret_; \
+ })
+
+#define ec_strdup(s) ({ \
+ void *ret_; \
+ if (ec_malloc_handler.malloc == NULL) \
+ ret_ = strdup(s); \
+ else \
+ ret_ = __ec_strdup(s); \
+ ret_; \
+ })
+
+#define ec_strndup(s, n) ({ \
+ void *ret_; \
+ if (ec_malloc_handler.malloc == NULL) \
+ ret_ = strndup(s, n); \
+ else \
+ ret_ = __ec_strndup(s, n); \
+ ret_; \
+ })
+
+
+#endif
const char *s;
int ret = -1;
- p = ec_tk_parse(tk, input, 0);
+ p = ec_tk_parse(tk, input);
s = ec_parsed_tk_to_string(p);
if (s == NULL && expected == NULL)
ret = 0;
const char *s;
int ret = -1;
- p = ec_tk_complete(tk, input, 0);
+ p = ec_tk_complete(tk, input);
s = ec_completed_tk_smallest_start(p);
if (s == NULL && expected == NULL)
ret = 0;
#include <string.h>
#include <assert.h>
+#include <ecoli_malloc.h>
#include <ecoli_tk.h>
struct ec_tk *ec_tk_new(const char *id, const struct ec_tk_ops *ops,
assert(size >= sizeof(*tk));
- tk = calloc(1, size);
+ tk = ec_calloc(1, size);
if (tk == NULL)
goto fail;
if (id != NULL) {
- tk->id = strdup(id);
+ tk->id = ec_strdup(id);
if (tk->id == NULL)
goto fail;
}
if (tk->ops != NULL && tk->ops->free_priv != NULL)
tk->ops->free_priv(tk);
- free(tk->id);
- free(tk);
+ ec_free(tk->id);
+ ec_free(tk);
}
-struct ec_parsed_tk *ec_tk_parse(const struct ec_tk *token, const char *str,
- size_t off)
+struct ec_parsed_tk *ec_tk_parse(const struct ec_tk *token, const char *str)
{
struct ec_parsed_tk *parsed_tk;
- parsed_tk = token->ops->parse(token, str, off);
+ parsed_tk = token->ops->parse(token, str);
return parsed_tk;
}
{
struct ec_parsed_tk *parsed_tk;
- parsed_tk = calloc(1, sizeof(*parsed_tk));
+ parsed_tk = ec_calloc(1, sizeof(*parsed_tk));
if (parsed_tk == NULL)
goto fail;
TAILQ_REMOVE(&parsed_tk->children, child, next);
ec_parsed_tk_free(child);
}
- free(parsed_tk->str);
- free(parsed_tk);
+ ec_free(parsed_tk->str);
+ ec_free(parsed_tk);
}
static void __ec_parsed_tk_dump(const struct ec_parsed_tk *parsed_tk,
}
struct ec_completed_tk *ec_tk_complete(const struct ec_tk *token,
- const char *str, size_t off)
+ const char *str)
{
struct ec_completed_tk *completed_tk;
- completed_tk = token->ops->complete(token, str, off);
+ completed_tk = token->ops->complete(token, str);
return completed_tk;
}
{
struct ec_completed_tk *completed_tk = NULL;
- completed_tk = calloc(1, sizeof(*completed_tk));
+ completed_tk = ec_calloc(1, sizeof(*completed_tk));
if (completed_tk == NULL)
return NULL;
{
struct ec_completed_tk_elt *elt = NULL;
- elt = calloc(1, sizeof(*elt));
+ elt = ec_calloc(1, sizeof(*elt));
if (elt == NULL)
return NULL;
elt->tk = tk;
- elt->add = strdup(add);
- elt->full = strdup(full);
+ elt->add = ec_strdup(add);
+ elt->full = ec_strdup(full);
if (elt->add == NULL || elt->full == NULL) {
ec_completed_tk_elt_free(elt);
return NULL;
completed_tk->count++;
if (elt->add != NULL) {
if (completed_tk->smallest_start == NULL) {
- completed_tk->smallest_start = strdup(elt->add);
+ completed_tk->smallest_start = ec_strdup(elt->add);
} else {
n = strcmp_count(elt->add,
completed_tk->smallest_start);
void ec_completed_tk_elt_free(struct ec_completed_tk_elt *elt)
{
- free(elt->add);
- free(elt->full);
- free(elt);
+ ec_free(elt->add);
+ ec_free(elt->full);
+ ec_free(elt);
}
struct ec_completed_tk *ec_completed_tk_merge(
TAILQ_REMOVE(&completed_tk->elts, elt, next);
ec_completed_tk_elt_free(elt);
}
- free(completed_tk->smallest_start);
- free(completed_tk);
+ ec_free(completed_tk->smallest_start);
+ ec_free(completed_tk);
}
void ec_completed_tk_dump(const struct ec_completed_tk *completed_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);
+ const char *str);
typedef struct ec_completed_tk *(*ec_tk_complete_t)(const struct ec_tk *tk,
- const char *str, size_t off);
+ const char *str);
typedef void (*ec_tk_free_priv_t)(struct ec_tk *);
struct ec_tk_ops {
};
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);
+struct ec_parsed_tk *ec_tk_parse(const struct ec_tk *token, const char *str);
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);
* 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);
+ const char *str);
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);
#include <ecoli_tk_empty.h>
static struct ec_parsed_tk *parse(const struct ec_tk *gen_tk,
- const char *str, size_t off)
+ const char *str)
{
struct ec_parsed_tk *parsed_tk;
return NULL;
(void)str;
- (void)off;
parsed_tk->str = strdup("");
return parsed_tk;
#include <ctype.h>
#include <errno.h>
+#include <ecoli_malloc.h>
#include <ecoli_tk.h>
#include <ecoli_tk_int.h>
#include <ecoli_test.h>
}
static struct ec_parsed_tk *parse(const struct ec_tk *gen_tk,
- const char *str, size_t off)
+ const char *str)
{
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);
+ len = parse_llint(tk, str, &val);
if (len == 0)
return NULL;
if (parsed_tk == NULL)
return NULL;
- parsed_tk->str = strndup(str + off, len);
+ parsed_tk->str = ec_strndup(str, len);
return parsed_tk;
}
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);
+ p = ec_tk_parse(tk, "0");
s = ec_parsed_tk_to_string(p);
if (s == NULL) {
TEST_ERR();
TEST_ERR();
}
- p = ec_tk_parse(tk, "10", 0);
+ p = ec_tk_parse(tk, "10");
s = ec_parsed_tk_to_string(p);
if (s == NULL) {
TEST_ERR();
"0x7fffffffffffffff");
ret |= EC_TEST_CHECK_TK_PARSE(tk, "-2", NULL);
- p = ec_tk_parse(tk, "10", 0);
+ p = ec_tk_parse(tk, "10");
s = ec_parsed_tk_to_string(p);
if (s == NULL) {
TEST_ERR();
#include <assert.h>
#include <stdarg.h>
+#include <ecoli_malloc.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)
+ const char *str)
{
struct ec_tk_or *tk = (struct ec_tk_or *)gen_tk;
struct ec_parsed_tk *parsed_tk, *child_parsed_tk;
return NULL;
for (i = 0; i < tk->len; i++) {
- child_parsed_tk = ec_tk_parse(tk->table[i], str, off);
+ child_parsed_tk = ec_tk_parse(tk->table[i], str);
if (child_parsed_tk != NULL)
break;
}
ec_parsed_tk_add_child(parsed_tk, child_parsed_tk);
- parsed_tk->str = strndup(child_parsed_tk->str,
+ parsed_tk->str = ec_strndup(child_parsed_tk->str,
strlen(child_parsed_tk->str));
return parsed_tk;
}
static struct ec_completed_tk *complete(const struct ec_tk *gen_tk,
- const char *str, size_t off)
+ const char *str)
{
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);
+ child_completed_tk = ec_tk_complete(tk->table[n], str);
if (child_completed_tk == NULL)
continue;
{
struct ec_tk_or *tk = (struct ec_tk_or *)gen_tk;
- free(tk->table);
+ ec_free(tk->table);
}
static struct ec_tk_ops or_ops = {
return &tk->gen;
fail:
- free(tk);
+ ec_free(tk);
return NULL;
}
return &tk->gen;
fail:
- free(tk); // XXX use tk_free? we need to delete all child on error
+ ec_free(tk); // XXX use tk_free? we need to delete all child on error
va_end(ap);
return NULL;
}
#include <assert.h>
#include <stdarg.h>
+#include <ecoli_malloc.h>
#include <ecoli_tk.h>
#include <ecoli_tk_seq.h>
+// XXX to handle the quote, it will be done in tk_shseq
+// it will unquote the string and parse each token separately
static struct ec_parsed_tk *parse(const struct ec_tk *tk,
- const char *str, size_t off)
+ const char *str)
{
struct ec_tk_seq *seq = (struct ec_tk_seq *)tk;
struct ec_parsed_tk *parsed_tk, *child_parsed_tk;
return NULL;
for (i = 0; i < seq->len; i++) {
- child_parsed_tk = ec_tk_parse(seq->table[i], str, off + len);
+ child_parsed_tk = ec_tk_parse(seq->table[i], str + len);
if (child_parsed_tk == NULL)
goto fail;
ec_parsed_tk_add_child(parsed_tk, child_parsed_tk);
}
- parsed_tk->str = strndup(str + off, len);
+ parsed_tk->str = ec_strndup(str, len);
return parsed_tk;
return &tk->gen;
fail:
- free(tk);
+ ec_free(tk);
return NULL;
}
return &tk->gen;
fail:
- free(tk); // XXX use tk_free? we need to delete all child on error
+ ec_free(tk); // XXX use tk_free? we need to delete all child on error
va_end(ap);
return NULL;
}
#include <string.h>
#include <ctype.h>
+#include <ecoli_malloc.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)
+ const char *str)
{
struct ec_parsed_tk *parsed_tk;
size_t len = 0;
- if (!isspace(str[off]))
+ if (!isspace(str[0]))
return NULL;
parsed_tk = ec_parsed_tk_new(gen_tk);
if (parsed_tk == NULL)
return NULL;
- while (isspace(str[off + len]))
+ while (isspace(str[len]))
len++;
- parsed_tk->str = strndup(str + off, len);
+ parsed_tk->str = ec_strndup(str, len);
return parsed_tk;
}
#include <stdlib.h>
#include <string.h>
+#include <ecoli_malloc.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)
+ const char *str)
{
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)
+ if (strncmp(str, 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);
+ parsed_tk->str = ec_strndup(str, tk->len);
return parsed_tk;
}
static struct ec_completed_tk *complete(const struct ec_tk *gen_tk,
- const char *str, size_t off)
+ const char *str)
{
struct ec_tk_str *tk = (struct ec_tk_str *)gen_tk;
struct ec_completed_tk *completed_tk;
size_t n;
for (n = 0; n < tk->len; n++) {
- if (str[off + n] != tk->string[n])
+ if (str[n] != tk->string[n])
break;
}
- if (str[off + n] != '\0')
+ if (str[n] != '\0')
return NULL;
completed_tk = ec_completed_tk_new();
{
struct ec_tk_str *tk = (struct ec_tk_str *)gen_tk;
- free(tk->string);
+ ec_free(tk->string);
}
static struct ec_tk_ops str_ops = {
if (tk == NULL)
goto fail;
- s = strdup(str);
+ s = ec_strdup(str);
if (s == NULL)
goto fail;
return &tk->gen;
fail:
- free(s);
- free(tk);
+ ec_free(s);
+ ec_free(tk);
return NULL;
}
}
/* ok */
- p = ec_tk_parse(seq, "hello mike", 0);
+ p = ec_tk_parse(seq, "hello mike");
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);
+ p = ec_tk_parse(seq, "hello robert");
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);