shithub: fnt

Download patch

ref: 260b588d2228f593be128e9de725822b2ffac663
parent: 1d8152b420445c36407a1c5cf95932dc43922879
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Mon Jun 10 16:45:19 EDT 2024

multiple attributes; combine field and fieldarr

--- a/otf.rkt
+++ b/otf.rkt
@@ -47,42 +47,48 @@
   (-> type? positive?)
   (/ (type-bits t) 8))
 
-(define-struct field (type name unused)
+(define (field-unused? f)
+  (assoc 'unused (field-attrs f)))
+
+(define (field-count f)
+  (assoc 'count (field-attrs f)))
+
+(define (field-ptr f)
+  (if (field-count f) "*" ""))
+
+(define-struct field (type name attrs)
   #:transparent
   #:methods gen:code
   [(define/generic super-c-type c-type)
    (define (gen-h f)
-     (list (~a (if (field-unused f) "// unused " "")
+     (list (~a (if (field-unused? f) "// unused " "")
                (super-c-type (field-type f))
                " "
+               (field-ptr f)
                (field-name f)
                ";")))
    (define (gen-c f)
-     (list (if (field-unused f)
-               (~a "if(skip_bytes(ctx, " (type-size (field-type f)) ") < 0){")
-               (~a "if(read_" (type-name (field-type f)) "(ctx, &v->" (field-name f) ") < 0){"))
+     (define (size t)
+       (if (type? t) (type-size t) 0))
+     (define (name t)
+       (if (type? t) (type-name t) (cmplx-name t)))
+     (list (match (field-count f)
+             [#f
+              (if (field-unused? f)
+                  (~a "if(skip_bytes(ctx, " (size (field-type f)) ") < 0){")
+                  (~a "if(read_" (name (field-type f)) "(ctx, &v->" (field-name f) ") < 0){"))]
+             [count
+              (~a "if(read_array(ctx, &v->"
+                  (field-name f)
+                  ", read_"
+                  (super-c-type (field-type f))
+                  ", v->"
+                  (cadr count)
+                  ") < 0){")])
            (~a "\twerror(\"%s: %r\", \"" (field-name f) "\");")
            (~a "\tgoto err;")
            (~a "}")))])
 
-(define-struct (fieldarr field) (count)
-  #:transparent
-  #:methods gen:code
-  [(define/generic super-c-type c-type)
-   (define (gen-h a)
-     (list (~a (super-c-type (field-type a)) " *" (field-name a) ";")))
-   (define (gen-c a)
-     (list (~a "if(read_array(ctx, &v->"
-               (field-name a)
-               ", read_"
-               (super-c-type (field-type a))
-               ", v->"
-               (fieldarr-count a)
-               ") < 0){")
-           (~a "\twerror(\"%s: %r\", \"" (field-name a) "\");")
-           (~a "\tgoto err;")
-           (~a "}")))])
-
 (define-struct cmplx (name fields tag)
   #:transparent
   #:methods gen:code
@@ -135,21 +141,35 @@
          (set! cmplxs (append cmplxs (list typ))))]
     [(_ typ:id fields:expr) #'(mkcmplx typ fields "")]))
 
+(define-for-syntax fields '())
+
+(define-syntax (mkattr stx)
+  (syntax-parse stx
+    [(_ ({~literal =} vs:number ...+)) #''(= vs ...)]
+    [(_ ({~literal count} n:id))
+     (begin
+       (if (assoc (syntax->datum #`n) fields)
+           #''(count n)
+           (raise-syntax-error #f "no such field" stx #'n)))]
+    [(_ {~literal unused}) #''(unused #t)]))
+
 (define-syntax (mkfield stx)
   (syntax-parse stx
-    [(_ {~literal //} type:id name:id)
-     #'(field type
-              `name
-              #t)]
-    [(_ type:id name:id [count:id]) #'(fieldarr type `name #f `count)]
-    [(_ type:id name:id)
-     #'(field type
-              `name
-              #f)]))
+    [(_ type:id name:id attrs ...)
+     (begin
+       (let ([f #'(field type
+                         `name
+                         (list (mkattr [~@ attrs]) ...))])
+         (begin
+           (set! fields (append fields (list (syntax->datum #'(name type)))))
+           f)))]))
 
 (define-syntax (mkfields stx)
   (syntax-parse stx
-    [(_ x ...) #'(list (mkfield {~@ . x}) ...)]))
+    [(_ x ...)
+     (begin
+       (set! fields '())
+       #'(list (mkfield [~@ . x]) ...))]))
 
 (mktype uint8 8 u8int)
 (mktype int8 8 s8int)
@@ -177,30 +197,32 @@
 (mkcmplx TableRecord (mkfields {Tag tableTag} {uint32 checksum} {Offset32 offset} {uint32 length}))
 
 (mkcmplx TableDirectory
-         (mkfields {uint32 sfntVersion}
+         (mkfields {uint32 sfntVersion (= #x000100000 #x4f54544f)}
                    {uint16 numTables}
                    {uint16 searchRange}
                    {uint16 entrySelector}
                    {uint16 rangeShift}
-                   {TableRecord tableRecords [numTables]}))
+                   {TableRecord tableRecords (count numTables)}))
 
 (mkcmplx EncodingRecord
-         (mkfields {uint16 platformID} {uint16 encodingID} {Offset32 subtableOffset}))
+         (mkfields {uint16 platformID (= 0 1 2 3 4)} {uint16 encodingID} {Offset32 subtableOffset}))
 
 (mkcmplx TableCmap
-         (mkfields {uint16 version} {uint16 numTables} {EncodingRecord encodingRecords [numTables]})
+         (mkfields {uint16 version (= 0)}
+                   {uint16 numTables}
+                   {EncodingRecord encodingRecords (count numTables)})
          "cmap")
 
 (mkcmplx TableHead
-         (mkfields {uint16 majorVersion}
-                   {uint16 minorVersion}
+         (mkfields {uint16 majorVersion (= 1)}
+                   {uint16 minorVersion (= 0)}
                    {Fixed fontRevision}
                    {uint32 checksumAdjustment}
-                   {uint32 magicNumber}
+                   {uint32 magicNumber (= #x5f0f3cf5)}
                    {uint16 flags}
                    {uint16 unitsPerEm}
-                   {// LONGDATETIME created}
-                   {// LONGDATETIME modified}
+                   {LONGDATETIME created unused}
+                   {LONGDATETIME modified unused}
                    {int16 xMin}
                    {int16 yMin}
                    {int16 xMax}
@@ -207,9 +229,9 @@
                    {int16 yMax}
                    {uint16 macStyle}
                    {uint16 lowestRecPPEM}
-                   {int16 fontDirectionHint}
-                   {int16 indexToLocFormat}
-                   {int16 glyphDataFormat})
+                   {int16 fontDirectionHint unused (= -2 -1 0 1 2)}
+                   {int16 indexToLocFormat (= 0 1)}
+                   {int16 glyphDataFormat (= 0)})
          "head")
 
 (printf (format gen-h))