Commit f4ea1c85d0b3b075e0c838a92e99224d94ae78a1

Thomas de Grivel 2024-08-19T12:07:56

offsetof, fact_w

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