summary refs log tree commit diff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2016-11-20 23:34:36 +0100
committerLudovic Courtès <ludo@gnu.org>2016-11-21 00:34:48 +0100
commit8eb790f368be5d7beac728e55093b6a3ea22328b (patch)
tree417159a7d780fd54850b78131f2c55a98d332b50
parent1845c2a4362c96d7feea3132f21aec34a607f855 (diff)
downloadguix-8eb790f368be5d7beac728e55093b6a3ea22328b.tar.gz
syscalls: Add 'c-struct-field-offset'.
* guix/build/syscalls.scm (define-c-struct-macro): New macro.
(define-c-struct): Use it.
(c-struct-field-offset): New macro.
-rw-r--r--guix/build/syscalls.scm31
1 files changed, 31 insertions, 0 deletions
diff --git a/guix/build/syscalls.scm b/guix/build/syscalls.scm
index c3832f6d48..85de47d26e 100644
--- a/guix/build/syscalls.scm
+++ b/guix/build/syscalls.scm
@@ -267,6 +267,29 @@ result is the alignment of the \"most strictly aligned component\"."
                                         (align offset type0)
                                         type0))))))
 
+(define-syntax define-c-struct-macro
+  (syntax-rules ()
+    "Define NAME as a macro that can be queried to get information about the C
+struct it represents.  In particular:
+
+  (NAME field-offset FIELD)
+
+returns the offset in bytes of FIELD within the C struct represented by NAME."
+    ((_ name ((fields types) ...))
+     (define-c-struct-macro name
+       (fields ...) 0 ()
+       ((fields types) ...)))
+    ((_ name (fields ...) offset (clauses ...) ((field type) rest ...))
+     (define-c-struct-macro name
+       (fields ...)
+       (+ (align offset type) (type-size type))
+       (clauses ... ((_ field-offset field) (align offset type)))
+       (rest ...)))
+    ((_ name (fields ...) offset (clauses ...) ())
+     (define-syntax name
+       (syntax-rules (field-offset fields ...)
+         clauses ...)))))
+
 (define-syntax define-c-struct
   (syntax-rules ()
     "Define SIZE as the size in bytes of the C structure made of FIELDS.  READ
@@ -274,6 +297,8 @@ as a deserializer and WRITE! as a serializer for the C structure with the
 given TYPES.  READ uses WRAP-FIELDS to return its value."
     ((_ name size wrap-fields read write! (fields types) ...)
      (begin
+       (define-c-struct-macro name
+         ((fields types) ...))
        (define size
          (struct-size 0 () types ...))
        (define (write! bv offset fields ...)
@@ -281,6 +306,12 @@ given TYPES.  READ uses WRAP-FIELDS to return its value."
        (define* (read bv #:optional (offset 0))
          (read-types wrap-fields bv offset (types ...) ()))))))
 
+(define-syntax-rule (c-struct-field-offset type field)
+  "Return the offset in BYTES of FIELD within TYPE, where TYPE is a C struct
+defined with 'define-c-struct' and FIELD is a field identifier.  An
+expansion-time error is raised if FIELD does not exist in TYPE."
+  (type field-offset field))
+
 
 ;;;
 ;;; FFI.