diff --git a/libc3/compare.c b/libc3/compare.c
index f168b78..1453132 100644
--- a/libc3/compare.c
+++ b/libc3/compare.c
@@ -183,6 +183,7 @@ s8 compare_fact_unbound_var_count (const s_fact *a,
{
u8 a_count;
u8 b_count;
+ bool unbound;
if (a == b)
return 0;
if (!a)
@@ -191,17 +192,29 @@ s8 compare_fact_unbound_var_count (const s_fact *a,
return 1;
a_count = 0;
b_count = 0;
- if (tag_is_unbound_var(a->subject))
+ if (! tag_is_unbound_var(a->subject, &unbound))
+ return COMPARE_ERROR;
+ if (unbound)
a_count++;
- if (tag_is_unbound_var(a->predicate))
+ if (! tag_is_unbound_var(a->predicate, &unbound))
+ return COMPARE_ERROR;
+ if (unbound)
a_count++;
- if (tag_is_unbound_var(a->object))
+ if (! tag_is_unbound_var(a->object, &unbound))
+ return COMPARE_ERROR;
+ if (unbound)
a_count++;
- if (tag_is_unbound_var(b->subject))
+ if (! tag_is_unbound_var(b->subject, &unbound))
+ return COMPARE_ERROR;
+ if (unbound)
b_count++;
- if (tag_is_unbound_var(b->predicate))
+ if (! tag_is_unbound_var(b->predicate, &unbound))
+ return COMPARE_ERROR;
+ if (unbound)
b_count++;
- if (tag_is_unbound_var(b->object))
+ if (! tag_is_unbound_var(b->object, &unbound))
+ return COMPARE_ERROR;
+ if (unbound)
b_count++;
return compare_u8(a_count, b_count);
}
diff --git a/libc3/compare.h b/libc3/compare.h
index f891d7b..c55e859 100644
--- a/libc3/compare.h
+++ b/libc3/compare.h
@@ -15,6 +15,11 @@
#include "types.h"
+#define COMPARE_ERROR ((s8) -2)
+#define COMPARE_LT ((s8) -1)
+#define COMPARE_EQ ((s8) 0)
+#define COMPARE_GT ((s8) 1)
+
#define COMPARE_PROTOTYPE(type) \
s8 compare_##type (type a, type b)
diff --git a/libc3/facts_spec.c b/libc3/facts_spec.c
index 536d335..988c2b6 100644
--- a/libc3/facts_spec.c
+++ b/libc3/facts_spec.c
@@ -63,6 +63,7 @@ p_facts_spec facts_spec_sort (p_facts_spec spec)
uw count;
uw i = 0;
uw j;
+ s8 r;
assert(spec);
count = facts_spec_count_facts(spec);
if (count > 0)
@@ -71,8 +72,11 @@ p_facts_spec facts_spec_sort (p_facts_spec spec)
while (j < count - i - 1) {
a = spec + j * 4;
b = spec + (j + 1) * 4;
- if (compare_fact_unbound_var_count((s_fact *) a,
- (s_fact *) b) > 0) {
+ r = compare_fact_unbound_var_count((s_fact *) a,
+ (s_fact *) b);
+ if (r == COMPARE_ERROR)
+ return NULL;
+ if (r > 0) {
s_tag *swap[3];
swap[0] = a[0];
swap[1] = a[1];
diff --git a/libc3/facts_with.c b/libc3/facts_with.c
index c8e26b7..930c686 100644
--- a/libc3/facts_with.c
+++ b/libc3/facts_with.c
@@ -147,6 +147,7 @@ s_facts_cursor * facts_with_tags (s_facts *facts,
s_tag *predicate,
s_tag *object)
{
+ bool unbound;
s_tag *var_subject = NULL;
s_tag *var_predicate = NULL;
s_tag *var_object = NULL;
@@ -155,11 +156,17 @@ s_facts_cursor * facts_with_tags (s_facts *facts,
assert(subject);
assert(predicate);
assert(object);
- if (tag_is_unbound_var(subject))
+ if (! tag_is_unbound_var(subject, &unbound))
+ return NULL;
+ if (unbound)
var_subject = subject;
- if (tag_is_unbound_var(predicate))
+ if (! tag_is_unbound_var(predicate, &unbound))
+ return NULL;
+ if (unbound)
var_predicate = predicate;
- if (tag_is_unbound_var(object))
+ if (! tag_is_unbound_var(object, &unbound))
+ return NULL;
+ if (unbound)
var_object = object;
if (var_subject && var_predicate && var_object)
return facts_with_0(facts, cursor, var_subject, var_predicate,
diff --git a/libc3/facts_with_cursor.c b/libc3/facts_with_cursor.c
index 279cc38..b0e8183 100644
--- a/libc3/facts_with_cursor.c
+++ b/libc3/facts_with_cursor.c
@@ -50,9 +50,10 @@ const s_fact ** facts_with_cursor_next (s_facts_with_cursor *cursor,
err_puts("facts_with_cursor_next: pthread_mutex_lock");
assert(! "facts_with_cursor_next: pthread_mutex_lock");
exit(1);
+ return NULL;
}
if (! cursor->facts_count)
- goto ko;
+ goto not_found;
if (cursor->level == cursor->facts_count) {
level = &cursor->levels[cursor->facts_count - 1];
#ifdef DEBUG_FACTS
@@ -85,7 +86,7 @@ const s_fact ** facts_with_cursor_next (s_facts_with_cursor *cursor,
cursor->level--;
if (! cursor->level) {
cursor->facts_count = 0;
- goto ko;
+ goto not_found;
}
cursor->level--;
}
@@ -97,9 +98,10 @@ const s_fact ** facts_with_cursor_next (s_facts_with_cursor *cursor,
else
parent_spec = cursor->spec;
level->spec = facts_spec_new_expand(parent_spec);
- facts_with_tags(cursor->facts, &level->cursor,
- level->spec[0], level->spec[1],
- level->spec[2]);
+ if (! facts_with_tags(cursor->facts, &level->cursor,
+ level->spec[0], level->spec[1],
+ level->spec[2]))
+ goto ko;
}
#ifdef DEBUG_FACTS
buf_write_1(&g_c3_env.err, "[debug] cursor->level=");
@@ -126,7 +128,7 @@ const s_fact ** facts_with_cursor_next (s_facts_with_cursor *cursor,
level->spec = NULL;
if (! cursor->level) {
cursor->facts_count = 0;
- goto ko;
+ goto not_found;
}
cursor->level--;
}
@@ -137,6 +139,14 @@ const s_fact ** facts_with_cursor_next (s_facts_with_cursor *cursor,
}
*dest = fact;
return dest;
+ not_found:
+ if (pthread_mutex_unlock(&cursor->mutex)) {
+ err_puts("facts_with_cursor_next: pthread_mutex_unlock");
+ assert(! "facts_with_cursor_next: pthread_mutex_unlock");
+ exit(1);
+ }
+ *dest = NULL;
+ return dest;
ko:
if (pthread_mutex_unlock(&cursor->mutex)) {
err_puts("facts_with_cursor_next: pthread_mutex_unlock");
diff --git a/libc3/tag.c b/libc3/tag.c
index efe0688..d04f68d 100644
--- a/libc3/tag.c
+++ b/libc3/tag.c
@@ -652,9 +652,16 @@ bool tag_is_number (const s_tag *tag)
return false;
}
-bool tag_is_unbound_var (const s_tag *tag)
+bool * tag_is_unbound_var (const s_tag *tag, bool *dest)
{
- return (tag && tag->type == TAG_VAR);
+ assert(tag);
+ if (! tag) {
+ err_puts("tag_is_unbound_var: NULL tag");
+ assert(! "tag_is_unbound_var: NULL tag");
+ return NULL;
+ }
+ *dest = tag->type == TAG_VAR;
+ return dest;
}
bool tag_is_zero(const s_tag *tag)
diff --git a/libc3/tag.h b/libc3/tag.h
index 3e103a5..7edb651 100644
--- a/libc3/tag.h
+++ b/libc3/tag.h
@@ -48,7 +48,7 @@ s_str * tag_inspect (const s_tag *tag, s_str *dest);
bool tag_ident_is_bound (const s_tag *tag);
bool tag_is_bound_var (const s_tag *tag);
bool tag_is_number (const s_tag *tag);
-bool tag_is_unbound_var (const s_tag *tag);
+bool * tag_is_unbound_var (const s_tag *tag, bool *dest);
bool tag_is_zero(const s_tag *tag);
s8 tag_number_compare (const s_tag *a, const s_tag *b);
const s_tag * tag_resolve_cow (const s_tag *tag);
diff --git a/libc3/types.h b/libc3/types.h
index 0f2609b..7ab9cfa 100644
--- a/libc3/types.h
+++ b/libc3/types.h
@@ -191,12 +191,12 @@ typedef union tag_data u_tag_data;
typedef union tag_type u_tag_type;
/* typedefs */
-typedef u32 character;
-typedef s_tag **p_facts_spec;
-typedef s_tag *t_facts_spec[];
-typedef SHA1_CTX t_hash;
-typedef const s_tag *p_tag;
-typedef u64 t_skiplist_height;
+typedef u32 character;
+typedef s_tag **p_facts_spec;
+typedef s_tag *t_facts_spec[];
+typedef SHA1_CTX t_hash;
+typedef const s_tag *p_tag;
+typedef u64 t_skiplist_height;
/* function typedefs */
typedef void (* f_clean) (void *x);