summary refs log tree commit diff
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@irenes.space>2026-09-08 04:37:52 -0700
committerIrene Knapp <ireneista@irenes.space>2026-09-08 04:41:04 -0700
commit47bebc52ce2e9923be8ca4b7c144094f85d3c4b1 (patch)
treea21bf185f0e069756ee094d5e85be16cefc5ef58
parentd257a97b5d60f9521c1e2ba7e989e8523255e217 (diff)
add support for more prettiness features in the hex-transform's output
suffix comments can now have a negative length, which makes them cover a span anchored with the current point at its end rather than its start

magic comments can now request the suppression of metadata entries that would otherwise be generated

everything in elf.e has magic comments now

Force-Push: yes
Change-Id: I409982afdd346c2ecf91e4c24f96ca81f887b126
-rw-r--r--elf.e99
-rw-r--r--transform.e119
2 files changed, 165 insertions, 53 deletions
diff --git a/elf.e b/elf.e
index a149a0f..82af2f5 100644
--- a/elf.e
+++ b/elf.e
@@ -8,6 +8,10 @@
 ~
 ~   This relies on the label facility defined in labels.e. Make sure to load
 ~ that first.
+~
+~   This file makes use of magic comments for the hex transform, described in
+~ detail in transform.e, but its use is trivial and doesn't require accounting
+~ conventions.
 
 ~ ~~~~~~~~~~~~~~~~~~~~~
 ~ ~~ ELF file header ~~
@@ -25,40 +29,47 @@
 : elf-file-header
   ~ : blank-line
   ~ : ELF file header
-  ~ * denotes mandatory fields according to breadbox
+  ~ : indent
+  ~ : * denotes mandatory fields according to breadbox
   current-offset 3unroll
 
-  0x7f pack8 s" ELF" pack-raw-string    ~ *magic number
-  2 pack8                               ~ 64-bit
-  1 pack8                               ~ little-endian
-  1 pack8                               ~ ELF header format v1
-  0 pack8                               ~ System-V ABI
-  0 pack64                              ~ (padding)
+  ~ : 1 suppress
+  0x7f pack8 s" ELF" pack-raw-string  ~ : -4 *magic number
+  2 pack8                             ~ : -1 64-bit
+  1 pack8                             ~ : -1 little-endian
+  1 pack8                             ~ : -1 ELF header format v1
+  0 pack8                             ~ : -1 System-V ABI
+  0 pack64                            ~ : -8 (padding)
+  ~ : blank-line
 
-  2 pack16                              ~ *executable
-  0x3e pack16                           ~ *Intel x86-64
-  1 pack32                              ~ ELF format version
+  2 pack16                            ~ : -2 *executable
+  0x3e pack16                         ~ : -2 *Intel x86-64
+  1 pack32                            ~ : -4 ELF format version
+  ~ : blank-line
 
-  L@' cold-start L@' origin + pack64        ~ *entry point
+  L@' cold-start L@' origin + pack64  ~ : -8 *entry point
     ~ This includes the origin, intentionally.
 
-  L@' elf-program-header pack64         ~ *program header offset
+  L@' elf-program-header pack64       ~ : -8 *program header offset
     ~ We place the program header immediately after the ELF header. This
     ~ offset is from the start of the file.
-  0 pack64                              ~ section header offset
-  0 pack32                              ~ processor flags
+  0 pack64                            ~ : -8 section header offset
+  0 pack32                            ~ : -4 processor flags
+  ~ : blank-line
 
-  L@' elf-header-size pack16            ~ ELF header size
-  L@' elf-program-header-size pack16    ~ *program header entry size
-  1 pack16                              ~ *number of program header entries
-  0 pack16                              ~ section header entry size
-  0 pack16                              ~ number of section header entries
-  0 pack16                              ~ section name string table index
+  L@' elf-header-size pack16          ~ : -2 ELF header size
+  L@' elf-program-header-size pack16  ~ : -2 *program header entry size
+  1 pack16                            ~ : -2 *number of program header entries
+  0 pack16                            ~ : -2 section header entry size
+  0 pack16                            ~ : -2 number of section header entries
+  0 pack16                            ~ : -2 section name string table index
 
   ~   Though hardcoding the size of this header would work fine, it's easier
   ~ to use the label system to keep track of its size. The only place this is
   ~ actually referenced is right here in the header.
-  current-offset 4 roll - L!' elf-header-size ;
+  current-offset 4 roll - L!' elf-header-size
+  ~ : deindent
+  ;
 
 
 ~ ~~~~~~~~~~~~~~~~~~~~~~~~
@@ -90,26 +101,31 @@
 : elf-program-header
   ~ : blank-line
   ~ : ELF program header
+  ~ : indent
   ~ * denotes mandatory fields according to breadbox
   current-offset L!' elf-program-header
   current-offset 3unroll
 
-  1 pack32                              ~ *"loadable" segment type
-  0x05 pack32                           ~ *read+execute permission
-  0 pack64                              ~ *offset in file
-  L@' origin pack64                     ~ *virtual address
+  1 pack32                            ~ : -4 *"loadable" segment type
+  0x05 pack32                         ~ : -4 *read+execute permission
+  0 pack64                            ~ : -8 *offset in file
+  L@' origin pack64                   ~ : -8 *virtual address
     ~ required, but can be anything, subject to alignment
-  0 pack64                              ~ physical address (ignored)
+  0 pack64                            ~ : -8 physical address (ignored)
+  ~ : blank-line
 
-  L@' total-size pack64                 ~ *size in file
-  L@' total-size pack64                 ~ *size in memory
+  L@' total-size pack64               ~ : -8 *size in file
+  L@' total-size pack64               ~ : -8 *size in memory
+  ~ : blank-line
 
-  0 pack64                              ~ segment alignment
+  0 pack64                            ~ : 8 segment alignment
     ~ for relocation, but this doesn't apply to us
 
   ~   As with the file header, we use the label system to keep track of the
   ~ program header's size.
-  current-offset 4 roll - L!' elf-program-header-size ;
+  current-offset 4 roll - L!' elf-program-header-size
+  ~ : deindent
+  ;
 
 
 ~   This alternate version of the program header isn't used by evoke.e, but
@@ -118,26 +134,31 @@
 : elf-program-header-writable
   ~ : blank-line
   ~ : ELF program header
+  ~ : indent
   ~ * denotes mandatory fields according to breadbox
   current-offset L!' elf-program-header
   current-offset 3unroll
 
-  1 pack32                              ~ *"loadable" segment type
-  0x07 pack32                           ~ *read+write+execute permission
-  0 pack64                              ~ *offset in file
-  L@' origin pack64                     ~ *virtual address
+  1 pack32                            ~ : -4 *"loadable" segment type
+  0x07 pack32                         ~ : -4 *read+write+execute permission
+  0 pack64                            ~ : -8 *offset in file
+  L@' origin pack64                   ~ : -8 *virtual address
     ~ required, but can be anything, subject to alignment
-  0 pack64                              ~ physical address (ignored)
+  0 pack64                            ~ : -8 physical address (ignored)
+  ~ : blank-line
 
-  L@' total-size pack64                 ~ *size in file
-  L@' total-size pack64                 ~ *size in memory
+  L@' total-size pack64               ~ : -8 *size in file
+  L@' total-size pack64               ~ : -8 *size in memory
+  ~ : blank-line
 
-  0 pack64                              ~ segment alignment
+  0 pack64                            ~ : -8 segment alignment
     ~ for relocation, but this doesn't apply to us
 
   ~   As with the file header, we use the label system to keep track of the
   ~ program header's size.
-  current-offset 4 roll - L!' elf-program-header-size ;
+  current-offset 4 roll - L!' elf-program-header-size
+  ~ : deindent
+  ;
 
 ~ ~~~~~~~~~~~~~~~~
 ~ ~~ That's it! ~~
diff --git a/transform.e b/transform.e
index 77671cd..12c5483 100644
--- a/transform.e
+++ b/transform.e
@@ -2720,10 +2720,11 @@ allocate-transformation-state s" transformation-state" variable
 : hex-output-metadata-label-loop-buffer-start ;
 : hex-output-metadata-label-loop-buffer-length 8 + ;
 : hex-output-metadata-latest-output-point 2 8 * + ;
-: hex-output-metadata-is-fresh-line 3 8 * + ;
-: hex-output-metadata-indentation-depth 4 8 * + ;
-: hex-output-metadata-current-column 5 8 * + ;
-: hex-output-metadata-first-entry 6 8 * + ;
+: hex-output-metadata-suppression-count 3 8 * + ;
+: hex-output-metadata-is-fresh-line 4 8 * + ;
+: hex-output-metadata-indentation-depth 5 8 * + ;
+: hex-output-metadata-current-column 6 8 * + ;
+: hex-output-metadata-first-entry 7 8 * + ;
 : hex-output-metadata-entry-data-start ;
 : hex-output-metadata-entry-data-length 8 + ;
 : hex-output-metadata-entry-type 2 8 * + ;
@@ -2735,7 +2736,8 @@ allocate-transformation-state s" transformation-state" variable
 : hex-output-metadata-entry-type-blank-line 3 ;
 : hex-output-metadata-entry-type-indent 4 ;
 : hex-output-metadata-entry-type-string-literal 5 ;
-: hex-output-metadata-entry-type-alignment 6 ;
+: hex-output-metadata-entry-type-raw-string-literal 6 ;
+: hex-output-metadata-entry-type-alignment 7 ;
 
 ~   Initialize the contents of the output metadata to all zeroes. This is
 ~ called from hex-transform at its top level, at the very start, to make sure
@@ -2748,6 +2750,7 @@ allocate-transformation-state s" transformation-state" variable
   dup hex-output-metadata-label-loop-buffer-start 0 swap !
   dup hex-output-metadata-label-loop-buffer-length 0 swap !
   dup hex-output-metadata-latest-output-point 0 swap !
+  dup hex-output-metadata-suppression-count 0 swap !
   dup hex-output-metadata-is-fresh-line 1 swap !
   dup hex-output-metadata-indentation-depth 0 swap !
   dup hex-output-metadata-current-column 0 swap !
@@ -2781,6 +2784,16 @@ allocate-transformation-state s" transformation-state" variable
 
 ~ (data start, data length, entry type, string pointer --)
 : add-hex-output-metadata-entry
+  ~ If the suppression count is greater than zero, decrement it.
+  transformation-state transformation-state-output-metadata @
+  hex-output-metadata-suppression-count @
+  dup 0 < {
+    1-
+    transformation-state transformation-state-output-metadata @
+    hex-output-metadata-suppression-count !
+    4 ndrop exit
+  } { drop } if-else
+
   3 pick is-in-label-loop-buffer {
     transformation-state transformation-state-output-metadata @
     hex-output-metadata-first-entry
@@ -2810,6 +2823,11 @@ allocate-transformation-state s" transformation-state" variable
     crash
   } if-else ;
 
+~ (count adjustment --)
+: adjust-hex-output-suppression-count
+  transformation-state transformation-state-output-metadata @
+  hex-output-metadata-suppression-count dup @ 3roll + swap ! ;
+
 ~   This is the followup to zero-hex-output-metadata, above. Once we do have
 ~ the label-loop buffer, we need to create some default entries. This is
 ~ called in the first label-loop iteration by hex-allocate-replacement, and
@@ -3024,23 +3042,33 @@ allocate-transformation-state s" transformation-state" variable
       memmove
       ~ (entry pointer)
 
+      ~   We have a feature which lets a suffix comment be created with a
+      ~ negative length, which means it covers bytes before the current output
+      ~ point rather than after it. This logic here is the implementation of
+      ~ that feature.
+      dup hex-output-metadata-entry-data-start @ dup
+      2 pick hex-output-metadata-entry-data-length @ +
+      2dup min 3unroll max
+      ~ (entry pointer, low end of data, high end of data)
+
       ~   Now we have the original entry at the original location, and a copy
       ~ of it at the next location. We modify the original one in-place to
-      ~ turn it into a fresh-line entry...
-      dup hex-output-metadata-entry-type
+      ~ turn it into a fresh-line entry at the low end of the data...
+      2 pick hex-output-metadata-entry-type
       hex-output-metadata-entry-type-fresh-line swap !
 
-      dup hex-output-metadata-entry-data-length 0 swap !
+      2 pick hex-output-metadata-entry-data-start 3roll swap !
+      2 pick hex-output-metadata-entry-data-length 0 swap !
+      ~ (entry pointer, high end of data)
 
       ~   ... then we modify the next entry in-place to set its location to
       ~ the end of the data instead of the beginning, and its length to zero.
-      dup hex-output-metadata-next-entry
-      ~ (entry pointer, next entry pointer)
+      over hex-output-metadata-next-entry
+      ~ (entry pointer, high end of data, next entry pointer)
 
-      dup hex-output-metadata-entry-data-length @
-      over hex-output-metadata-entry-data-start @ +
-      over hex-output-metadata-entry-data-start !
+      dup hex-output-metadata-entry-data-start 3roll swap !
       hex-output-metadata-entry-data-length 0 swap !
+      ~ (entry pointer)
 
       ~   This rule won't fire again on the fresh-line entry because it's of a
       ~ different type, and it won't fire on the modified suffix-comment entry
@@ -3122,7 +3150,22 @@ allocate-transformation-state s" transformation-state" variable
           fresh-line
           indentation-depth@ dup indent advance-current-column
 
-          ." ~ Null-terminated string literal: "
+          ." ~ String literal with null terminator: "
+          0x22 value@ emitstring drop
+          dup hex-output-metadata-entry-string @ emitstring
+          0x22 value@ emitstring drop
+
+          newline
+          1 is-fresh-line!
+          0 current-column!
+        } if
+
+        dup hex-output-metadata-entry-type @
+        hex-output-metadata-entry-type-raw-string-literal = {
+          fresh-line
+          indentation-depth@ dup indent advance-current-column
+
+          ." ~ String literal with no terminator: "
           0x22 value@ emitstring drop
           dup hex-output-metadata-entry-string @ emitstring
           0x22 value@ emitstring drop
@@ -3385,6 +3428,47 @@ allocate-transformation-state s" transformation-state" variable
     exit
   } if
 
+  ~ This is highly similar to packstring.
+  dup s" pack-raw-string" stringcmp 0 = {
+    create dropstring
+    s" docol" find entry-to-execution-token execute ,
+    make-hidden
+
+    ~ (output point, string pointer)
+    s" 2dup" find entry-to-execution-token ,
+    s" dup" find entry-to-execution-token ,
+    s" stringlen" find entry-to-execution-token ,
+    ~ (output point, string pointer, string length NOT including terminator)
+
+    ~   Before we add the metadata entry, we also want to call hex-pack-trace
+    ~ to make sure latest-output-point gets adjusted for the string.
+    ~ Otherwise, we'd see magic comments in the wrong place.
+    s" 3roll" find entry-to-execution-token ,
+    s" dup" find entry-to-execution-token ,
+    s" lit" find entry-to-execution-token ,
+    4 ,
+    s" unroll" find entry-to-execution-token ,
+    s" swap" find entry-to-execution-token ,
+    s" dup" find entry-to-execution-token ,
+    s" 3unroll" find entry-to-execution-token ,
+    ~ (output point, string pointer, string length NOT including terminator,
+    ~  output point, string length NOT including terminator)
+    ' hex-pack-trace entry-to-execution-token ,
+
+    ~ (output point, string pointer, string length including terminator)
+    s" swap" find entry-to-execution-token ,
+    ' hex-output-metadata-entry-type-raw-string-literal
+    entry-to-execution-token ,
+    s" swap" find entry-to-execution-token ,
+    ' add-hex-output-metadata-entry entry-to-execution-token ,
+    ~ (output point, string pointer)
+    ~ Fall through to the inner implementation.
+
+    ' ] entry-to-execution-token execute
+    exit
+  } if
+
+
   dup s" pack8" stringcmp 0 = {
     create dropstring
     s" docol" find entry-to-execution-token execute ,
@@ -3888,6 +3972,13 @@ allocate-transformation-state s" transformation-state" variable
     exit
   } if
 
+  dup s" suppress" stringcmp 0 = {
+    ~   Suppress the next N entries, or adjust the remaining count of entries
+    ~ to suppress.
+    drop swap drop adjust-hex-output-suppression-count
+    exit
+  } if
+
   dup s" fresh-line" stringcmp 0 = {
     ~ Create a new fresh-line entry.
     drop hex-output-metadata-entry-type-fresh-line 0