diff --git a/.gitignore b/.gitignore
index 027d744..bc06626 100644
--- a/.gitignore
+++ b/.gitignore
@@ -51,6 +51,7 @@ lib/kc3/0.1/socket.so
.libs/
*.lo
macos/kc3-v*
+/misc/fact_w_offsets
/misc/http_request_offsets
/misc/http_response_offsets
/misc/print_limits
diff --git a/lib/kc3/0.1/kc3.facts b/lib/kc3/0.1/kc3.facts
index 021d2f8..04c1346 100644
--- a/lib/kc3/0.1/kc3.facts
+++ b/lib/kc3/0.1/kc3.facts
@@ -273,3 +273,5 @@ add {KC3, :symbol, KC3.errno}
replace {KC3.errno, :symbol_value, cfn Sw "kc3_errno" ()}
add {KC3, :symbol, KC3.strerror}
replace {KC3.strerror, :symbol_value, cfn Str "kc3_strerror" (Sw, Result)}
+add {KC3, :symbol, KC3.offsetof}
+replace {KC3.offsetof, :symbol_value, cfn Uw "kc3_offsetof" (Sym, Sym, Result)}
diff --git a/libkc3/kc3.c b/libkc3/kc3.c
index 560fecd..03e7c6c 100644
--- a/libkc3/kc3.c
+++ b/libkc3/kc3.c
@@ -28,6 +28,7 @@
#include "map.h"
#include "str.h"
#include "struct.h"
+#include "struct_type.h"
#include "sym.h"
#include "tag.h"
@@ -308,6 +309,19 @@ bool * kc3_must_clean (const s_sym * const *sym, bool *dest)
return sym_must_clean(*sym, dest);
}
+uw * kc3_offsetof (const s_sym * const *module,
+ const s_sym * const *key, uw *dest)
+{
+ uw i = 0;
+ const s_struct_type *st;
+ if (! struct_type_find(*module, &st) ||
+ ! st ||
+ ! struct_type_find_key_index(st, *key, &i))
+ return NULL;
+ *dest = st->offset[i];
+ return dest;
+}
+
s_tag * kc3_pin (const s_tag *a, s_tag *dest)
{
if (! env_eval_tag(&g_kc3_env, a, dest))
diff --git a/libkc3/kc3_main.h b/libkc3/kc3_main.h
index 25d2f7e..30abbbc 100644
--- a/libkc3/kc3_main.h
+++ b/libkc3/kc3_main.h
@@ -38,6 +38,8 @@ uw * kc3_facts_next_id (uw *dest);
s_str * kc3_getenv (const s_str *name, s_str *dest);
void kc3_license (void);
const s_sym ** kc3_module (const s_sym **dest);
+uw * kc3_offsetof (const s_sym * const *module,
+ const s_sym * const *field, uw *dest);
sw kc3_puts (const s_tag *tag);
/* Operators. */
diff --git a/libkc3/struct.c b/libkc3/struct.c
index 0734302..d49ae07 100644
--- a/libkc3/struct.c
+++ b/libkc3/struct.c
@@ -150,21 +150,10 @@ void struct_delete (s_struct *s)
free(s);
}
-bool struct_find_key_index (const s_struct *s, const s_sym *key,
+uw * struct_find_key_index (const s_struct *s, const s_sym *key,
uw *dest)
{
- uw i = 0;
- assert(s);
- assert(key);
- while (i < s->type->map.count) {
- assert(s->type->map.key[i].type == TAG_SYM);
- if (s->type->map.key[i].data.sym == key) {
- *dest = i;
- return true;
- }
- i++;
- }
- return false;
+ return struct_type_find_key_index(s->type, key, dest);
}
const void * struct_get (const s_struct *s, const s_sym *key)
diff --git a/libkc3/struct.h b/libkc3/struct.h
index b13bd47..7f3a4d0 100644
--- a/libkc3/struct.h
+++ b/libkc3/struct.h
@@ -51,7 +51,7 @@ s_tag * struct_access (const s_struct *s,
s_tag *dest);
s_tag * struct_access_sym (const s_struct *s, const s_sym *key,
s_tag *dest);
-bool struct_find_key_index (const s_struct *s,
+uw * struct_find_key_index (const s_struct *s,
const s_sym *key, uw *dest);
const void * struct_get (const s_struct *s, const s_sym *key);
const s_sym ** struct_get_type (const s_struct *s, const s_sym *key,
diff --git a/libkc3/struct_type.c b/libkc3/struct_type.c
index 8012a7c..111b904 100644
--- a/libkc3/struct_type.c
+++ b/libkc3/struct_type.c
@@ -73,6 +73,23 @@ const s_struct_type ** struct_type_find (const s_sym *module,
return env_struct_type_find(&g_kc3_env, module, dest);
}
+uw * struct_type_find_key_index (const s_struct_type *st,
+ const s_sym *key, uw *dest)
+{
+ uw i = 0;
+ assert(st);
+ assert(key);
+ while (i < st->map.count) {
+ assert(st->map.key[i].type == TAG_SYM);
+ if (st->map.key[i].data.sym == key) {
+ *dest = i;
+ return dest;
+ }
+ i++;
+ }
+ return NULL;
+}
+
s_struct_type * struct_type_init (s_struct_type *st,
const s_sym *module,
const s_list *spec)
diff --git a/libkc3/struct_type.h b/libkc3/struct_type.h
index 046a05a..48c243d 100644
--- a/libkc3/struct_type.h
+++ b/libkc3/struct_type.h
@@ -50,6 +50,8 @@ bool * struct_type_exists (const s_sym *module,
bool *dest);
const s_struct_type ** struct_type_find (const s_sym *module,
const s_struct_type **dest);
+uw * struct_type_find_key_index
+(const s_struct_type *st, const s_sym *key, uw *dest);
uw struct_type_padding (uw offset, uw size);
#endif /* LIBKC3_STRUCT_TYPE_H */
diff --git a/misc/Makefile b/misc/Makefile
index a233ae0..f252584 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -14,7 +14,7 @@ CLEANFILES = http_request_offsets http_response_offsets print_limits
CPPFLAGS += -I/usr/local/include -I.. -W -Wall -Werror
-all: http_request_offsets http_response_offsets print_limits
+all: fact_w_offsets http_request_offsets http_response_offsets print_limits
build: all
@@ -23,6 +23,9 @@ clean:
distclean: clean
+fact_w_offsets: fact_w_offsets.c
+ ${CC} ${CPPFLAGS} -I.. fact_w_offsets.c -o fact_w_offsets
+
http_request_offsets: http_request_offsets.c
${CC} ${CPPFLAGS} -I.. http_request_offsets.c -o http_request_offsets
diff --git a/misc/fact_w_offsets.c b/misc/fact_w_offsets.c
new file mode 100644
index 0000000..d117dcd
--- /dev/null
+++ b/misc/fact_w_offsets.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <stddef.h>
+#include <assert.h>
+#include "../http/types.h"
+
+void print_offsets() {
+ printf("Offset of subject: %zu\n", offsetof(struct fact_w, subject));
+ printf("Offset of predicate: %zu\n", offsetof(struct fact_w, predicate));
+ printf("Offset of object: %zu\n", offsetof(struct fact_w, object));
+ printf("Offset of id: %zu\n", offsetof(struct fact_w, id));
+}
+
+int main (void) {
+ print_offsets();
+ return 0;
+}
diff --git a/test/ikc3/struct.kc3 b/test/ikc3/struct.kc3
index f147cff..f4be38d 100644
--- a/test/ikc3/struct.kc3
+++ b/test/ikc3/struct.kc3
@@ -8,3 +8,11 @@ quote [position: %GL.Vec3{},
[position: %GL.Vec3{},
normal: %GL.Vec3{},
tex_coord: %GL.Vec2{}]
+quote offsetof(FactW, :subject)
+offsetof(FactW, :subject)
+quote offsetof(FactW, :predicate)
+offsetof(FactW, :predicate)
+quote offsetof(FactW, :object)
+offsetof(FactW, :object)
+quote offsetof(FactW, :id)
+offsetof(FactW, :id)
diff --git a/test/ikc3/struct.out.expected b/test/ikc3/struct.out.expected
index 2cbc357..7f500b4 100644
--- a/test/ikc3/struct.out.expected
+++ b/test/ikc3/struct.out.expected
@@ -15,3 +15,11 @@
z: 0.0f},
tex_coord: %GL.Vec2{x: 0.0f,
y: 0.0f}]
+offsetof(FactW, :subject)
+(Uw) 0
+offsetof(FactW, :predicate)
+(Uw) 112
+offsetof(FactW, :object)
+(Uw) 224
+offsetof(FactW, :id)
+(Uw) 336